Flappy game version 2

object-oriented

int, Canvas (image, rect, rectMode, text, width, height, timer, keyIsPressed, keyCode), CanvasElement (move, resize, width, height)

You can create your own objects from classes by using the class name with round brackets. 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 user the timer function. Keep in mind that this time the timer function is bound to your instance of the canvas class. So you have to access the timer function through the instance variable. Also add the draw function.

def draw():
	pass
	
c = Canvas()

c.timer(draw)
The program should work so far. The draw function is called again and again at short intervals. Since the Ddraw 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.

c = Canvas()

c.timer(draw)

# Background
x = 0 
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 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.

def draw():
	global x
	background.move(x, 0)
	x = x - 4
	if x < -background.width() / 2:
		x = 0	# Background from start position
	
c = Canvas()

c.timer(draw)

# Background
x = 0 
background = c.image("C:\Images\Background.png")
c.height(background.height())
c.width(background.width() / 2)
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
yFlappy = background.height() / 2
xFlappy = background.width() / 2 / 2
flappy = c.image("C:\Images\Flappy.png", xFlappy, yFlappy)
When you start your program, Flappy should appear as desired. To move it, you use the keyCode function. Again, remember that this function 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.

def draw():
	global x, xFlappy, yFlappy
...
	# Flappy
	###############################
	if c.keyIsPressed() == True:
		if  c.keyCode() == UP:
			yFlappy = yFlappy - 5
		elif c.keyCode() == 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.

...
flappy = c.image("C:\Images\Flappy.png", xFlappy, yFlappy)

# Pillars
xPillar = -1
yPillarBelow = 0

c.rectMode(CORNER)
pillarAbove = c.rect() 
pillarBelow = c.rect()
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.

def draw():
	global x, xFlappy, yFlappy, xPillar, yPillar, yPillarBelow
...
	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.

def draw():
	global x, xFlappy, yFlappy, xPillar, yPillar, yPillarBelow, correct, wrong
...
	xPillar = xPillar - 5
	
	# Hit test
	#################################
	if xFlappy >= xPillar and xFlappy <= xPillar + 5:
		if yFlappy >= yPillarBelow-100 and yFlappy <= yPillarBelow-flappy.height():
			correct = correct + 1
		else:
			wrong = wrong + 1
...
pillarBelow = c.rect()

wrong = 0
correct = 0
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.

def draw():
	...
	# Hit test
	#################################
	if xFlappy >= xPillar and xFlappy <= xPillar + 5:
	...			
		text.text(f"good {correct} / bad {wrong}")

...
wrong = 0
correct = 0
text = c.text("");
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