Flappy game version 2

object-oriented

new, double, int, Canvas (Image, Rect, RectMode, Text, Width, Height, Timer, KeyIsPressed, KeyCode), CanvasElement (Move, Resize, Width, Height)

You can use the new operator to create your own objects from classes. Therefore, you can now program Flappy object-oriented using existing classes from the CoderLearn.Sketch library. You need the classes Canvas and CanvasElement for this.

Canvas

To create a new canvas, use the Canvas class. This has the same methods and predefined variables with the same parameters that you have previously used as functions, i.e. Line, Rect, Circle, Fill, etc. The difference now is that you can create multiple instances of paint surfaces. With the name of the instance variable, you then determine on which painting surface you draw.

Canvas c = new Canvas();
You can take a look at this by starting your program several times. With each call, an instance and thus a new painting surface is created on which you can draw.
You have already created the Canvas for the Flappy game. In order to draw time-controlled on the canvas, you can now set the timer variable. Keep in mind that this time the Timer variable is bound to your instance. So you have to access the Timer variable through the instance variable. Also add the Draw function.

	Canvas c = new Canvas();
	c.Timer = Draw;

	void Draw()
	{
	}
The program should work so far. The Draw function is called again and again at short intervals. Since the Draw function is not yet drawing, the painting area is of course still empty.

The background is moving

Start with the background and call the Image method. Again, be sure to call the method through the Canvas class instance variable c so that the image is drawn on the correct canvas.

	Canvas c = new Canvas();
	c.Timer = Draw;

	// Background
	double x; 
	CanvasElement background = c.Image(@"C:\Images\Background.png");
The Image method returns an instance of the CanvasElement class. So you get a single object returned, which you can use to move the image or change its size, for example. From the first Flappy version you already know that the x-coordinate has to change in order for the background to move from right to left. You can therefore create a variable x of the double data type outside of the draw function.
In the first Flappy version you also statically set the width and height of the window to the size of the image. You can now determine the size of the image directly via the CanvasElement class, which makes your program more flexible if the size of the background image changes.

	...
	CanvasElement background = c.Image(@"C:\Images\Background.png");

	c.Height = background.Height;
	c.Width = background.Width / 2;

	void Draw()
	{
		background.Move(x, 0);
		x = x - 4;
		if (x < -background.Width / 2)
			x = 0;  // Background from start position
	}
Each time the Draw function is called, you decrease the x variable by a fixed amount, say -4. You can now use the Move method to move the background image using the background instance variable. Since the background image disappears on the left edge after several runs, you must check again whether x is smaller than the width of the image. Also remember that the image must be duplicated as in the first flappy game version, i.e. appear twice in the image file and the beginning and end of the image must be identical. If the variable x is then at the negative value of half the width of the background, it must be set to 0 again.

Flappy appears on the canvas

Now Flappy should appear. You proceed exactly as you did with the background image. You can use the Image method of the Canvas class to return an instance of the CanvasElement class. You note the x and y coordinates in the two variables xFlappy and yFlappy. Flappy's starting position is again the center of the canvas. Since the background image appears twice in the image file, the x coordinate needs to be divided by 2 twice, once to split it in half and then to get Flappy in the middle of the image.

	...
	c.Width = background.Width / 2;

	// Flappy
	double yFlappy = background.Height / 2;
	double xFlappy = background.Width / 2 / 2;
	CanvasElement flappy = c.Image(@"C:\Images\Flappy.png", xFlappy, yFlappy);
	void Draw()
	{
	...
When you start your program, Flappy should appear as desired. To move it, you use the KeyCode variable. Again, remember that this variable belongs to the Canvas class instance, so you access the variable using the dot notation. When the cursor up or down key is pressed, Flappy should move 5 pixels in the corresponding direction. To do this, decrease or increase the variable yFlappy. Flappy can then use the Move method to change its position.

	...
	void Draw()
	{
	...
		// Flappy
		////////////////////
		if (c.KeyIsPressed == true)
		{
			if (c.KeyCode == KeyCodes.Up)
				yFlappy = yFlappy - 5;
			else if (c.KeyCode == KeyCodes.Down)
				yFlappy = yFlappy + 5;
		}
		flappy.Move(xFlappy, yFlappy);
	}

...now only the pillars are missing

In order for the pillars to move, you need a variable for the x-coordinate. Both columns should be drawn as a rectangle using the Rect method. You also need the y-coordinate for the bottom pillar, as this changes for the bottom pillar. You also need the variable yPillarBelow to calculate the height of the two pillars. Then you draw the two rectangles outside of the Draw function. The Rect method then returns an instance of the CanvasElement class, which you can use to change the size and position of the rectangles.

	...
	// Pillars
	double xPillar = -1;
	double yPillarBelow;

	c.RectMode(RectModes.Corner);
	CanvasElement pillarAbove = c.Rect(); 
	CanvasElement pillarBelow = c.Rect(); 

	void Draw()
	{
	...
To create the rectangles, no size and position are specified yet, so the position and size are set to 0. In the Draw function you now change the position and size of the rectangles. To do this, you set the xPillar and yPillarBelow variables if the x-coordinate has become negative. Set xPillar back to the position on the right side, i.e. to the width of the canvas. For yPillarBelow you determine a random number between 100 and the height of the canvas minus 100.

	...
		flappy.Move(xFlappy, yFlappy);

		// Pillars
		////////////////////
		if(xPillar < 0)
		{
			xPillar = c.Width;
			yPillarBelow = Random(100, c.Height - 100);
		}
		pillarAbove.Move(xPillar, 0);
		pillarAbove.Resize(20, yPillarBelow-100); 
		pillarBelow.Move(xPillar, yPillarBelow);
		pillarBelow.Resize(20, 600 - yPillarBelow);

		xPillar = xPillar - 5;
Then the two pillars can be moved using Move and the size can be changed using Resize. First you pass the width and then the height of the rectangle to resize. To move the pillars to the left, you reduce the x-coordinate xPillar by 5.

Flappy hits the gap

Flappy is currently ignoring the gap between the two pillars. In order to successfully pass the "flight path" you must first check the x-coordinates of Flappy and the pillars. Once Flappy has flown to the pillar, use the y-coordinates yFlappy and yPillarBelow to test if Flappy is inside the gap. If this is the case, a new variable correct is increased by 1, otherwise the variable wrong.

	...
		xPillar = xPillar - 5;

		// Hit test
		////////////////////
		if(xFlappy >= xPillar && xFlappy <= xPillar + 5)
		{
			if(yFlappy >= yPillarBelow-100 && 
			   yFlappy <= yPillarBelow-flappy.Height)
				correct = correct + 1;
			else
				wrong = wrong + 1;
		}    
	}
To make the correct and wrong variables appear on the canvas, call the Text method of the Canvas class. As with calling the Image or Rect method, this returns an instance of the CanvasElement class, which you can use to set the text.

	...
	CanvasElement pillarBelow = c.Rect(); 

	// result
	int correct;
	int wrong;
	CanvasElement text = c.Text("");

	void Draw()
	{
	...
		// Hit test
		////////////////////
		if(xFlappy >= xPillar && xFlappy <= xPillar + 5)
		{
	...
			text.Text($"good {correct} / bad {wrong}");
		}    
	}
You have now programmed the Flappy game with objects. You have not yet created your own classes, but used the Canvas and CanvasElement classes for this. If you compare the scope with the first solution, you will find that the object-oriented program contains a few more lines of code.
However, your current programming code has some advantages: You only create the individual elements on the drawing area once and not every time you call Draw. Your programming code is a bit more readable and maintainable, but above all more flexible. You should now be able to swap out the two images for the background and Flappy without adjusting constant values like the width of the background image or the height of Flappy.

Download source code

 This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License