Piader – virtual lcd

We have our game and we have our vlcd. Lets mix it together.

Our goal is to create one vlcd 16×6 for game and small 4×4 for displaying score. Something like this:

layout_right

Why right alignment ? Because I have short wires 🙂

Download source code

Prepare for Piader v 1.1

First quick cleanup. Move file piader.py from root into piader package and rename it to main.py. Next rename piader direcory to piader_1. Then duplicate this directory to piader_1-1. Now fix all imports 🙂 Remember also to add to main.py

import sys
sys.path.append("../")

before other imports.

I want old version without vlcd to exist.

Virtual lcd

We are ready ! Open main.py from piader_1.1. Change content to:


#!/usr/bin/python
# -*- coding: utf-8 -*-

"""Game launcher"""


import sys
sys.path.append("../")
import RPi.GPIO as GPIO #pylint: disable=I0011,F0401
from charlcd import lcd_buffered
from charlcd.drivers.gpio import Gpio
from charlcd.drivers.i2c import I2C
from charlcd import lcd_virtual_buffered
import game

GPIO.setmode(GPIO.BCM)


def main():
    """set lcds and start game"""
    lcd_two = lcd_buffered.CharLCD(16, 2, I2C(0x20, 1),
                                   cursor_blink=0, cursor_visible=0)
    lcd_two.init()
    lcd_one = lcd_buffered.CharLCD(20, 4, Gpio(),
                                   cursor_blink=0, cursor_visible=0)
    lcd_one.init()

    vlcd_main = lcd_virtual_buffered.CharLCD(16, 6)
    vlcd_main.init()
    vlcd_main.add_display(0, 0, lcd_one, 4, 0)
    vlcd_main.add_display(0, 4, lcd_two)

    vlcd_support = lcd_virtual_buffered.CharLCD(4, 4)
    vlcd_support.add_display(0, 0, lcd_one)
    vlcd_support.init()

    my_game = game.Piader([vlcd_main, vlcd_support])
    my_game.game()

main()


We have vlcd_main as game board and vlcd_support as additional informations.

Open Game class, we need to tweak a width const, change it to 16 from 20. In __init__ add

self.score = 0

Time for few modification in tick, remove

self.lcds[1].buffer_clear()

and

self.lcds[1].flush()

add (before flush that was left)

self.lcds[1].write(str(self.score), 0, 0)

See that we are not flushing lcd[1]. It’s because we are always flushing whole lcd buffer even when vlc taks onle small part of it.

Now we will add point counter, find function collision_check and after enemy_hit(source, target) add

self.score += 1

Last thing we need to do is change how function draw behave. Its much simpler, see for yourself:


    def draw(self, item):
        """draw sprite on screen"""
        (position_x, position_y) = item.get_position()

        if position_y > 5 or position_y < 0:
            self.objects.remove(item)
            item.event_discard()
            return

        self.lcds[0].write(item.get_sprite(), position_x, position_y)

To make things nicer lets change ‘Game Over’ position:

self.lcds[0].write("Game Over", 2, 2)

And remove init() function. Game shouldn’t care about lcds. Initializing things goes to main.py

Now start game, it should be working 🙂 Its for me 🙂

VLCD improvements

One thing that is annoying me is fact that we are manually calling init on each buffered lcd that goes to buffered vlcd. We shouldn’t be doing this, its job for vlcd. We can’t allow double init. So we start with flag initialize, add

self.initialized = False

to lcd_buffered.py and lcd_virtual_buffered.py into function __init__ at any place.

Now modify init by adding

self.initialized = True

at the end and

if self.initialized:
    return

at the beginning.

This code goes only to lcd_virtual_buffered (just before initialized = True):


for display in self.displays:
    display['lcd'].init()

To make sure we have lcds to init we will check displays dictionary and if its empty raise an exception. This will force us to first add displays to vlcd and then call init. Do so by adding

if len(self.displays) == 0:
    raise ValueError("Add lcd before init vlcd")

to init just after initalized check.

Stop! Jenkins time!

  • forget to run unit tests, they start to fail because of initialized flag
  • one test should be deleted long ago but it was passing.. and it shouldn’t
  • cpd ratio is soo high, we have two copied of Piader 🙂
  • one pylint error is present, Direct class in direct_interface.py has only one function, seems its bad 🙂

Summary

This time we refactored our small game to use vlcds, one as game board and second as scoreboard. We also added initialized flag and lcd initialiaztion into vlcd init function. That mean less code for doing more in your app 🙂

Download source code

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s