Faisons une rupture de bloc avec wxPython

introduction

Une vidéo de Google Deepmind qui applique le Deep Q Learning à Break Out d'ATARI pour la capturer est devenue populaire. (La vidéo est ici) J'ai décidé d'essayer cela moi-même et j'ai pensé que ce serait utile plus tard, alors j'ai commencé par fabriquer moi-même un brise-bloc. La raison pour laquelle j'ai utilisé wxPython était parce que je voulais que la bibliothèque Deep Learning soit utilisée plus tard pour être basée sur Python.

Il reste encore un long chemin à parcourir avant le Deep Q Learning, mais j'ai écrit un article dans l'espoir qu'il serait utile pour créer une application d'animation à l'aide de wxPython.

Il nécessite wxPython pour fonctionner. La méthode d'installation est [ici](http://qiita.com/kanlkan/items/5e6f2e63de406f46b3b1#wxpython%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83 Veuillez consulter% 88% E3% 83% BC% E3% 83% AB) et ainsi de suite.

Code source

Il est également posté sur GitHub, mais ce n'est pas si long, donc je le posterai ici aussi.

break-wall.py


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

# break-wall.py
#

import wx
import random
import math

gVersion = "0.8.0"
gGameState = ("INIT","PLAYING","END")
gTimerInterval = 5 # [msec]
gFieldWidth = 640
gFieldHeight = 720
gFieldColor = (230,230,160)
gBarIniPos = (300, 640)
gBarSize = (120, 20)
gBarColor = (90, 170, 90)
gBarSpeed = 12 
gBallRadius = 8
gBallColor = (0, 0, 255)
gIniBallSpeed = 2
gBlkTop = 120
gBlkVCnt = 8
gBlkHCnt = 3
gBlkSize = (80, 40)
gBlkColor = ((255,0,0),(0,255,0),(0,0,255))

class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, 'Break Wall :' + gVersion, \
                          size=(gFieldWidth + 4, gFieldHeight + 4), \
                          style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
        self.main_field = FieldPanel(self)

        self.Bind(wx.EVT_CLOSE, self.onClose)
        self.Bind(wx.EVT_TIMER, self.onTimer)

        self.timer = wx.Timer(self)
        self.timer.Start(gTimerInterval)

    def onClose(self, event):
        self.timer.Stop()
        self.Destroy()

    def onTimer(self, event):
        self.main_field.update()


class FieldPanel(wx.Panel):
    def __init__(self, parent, pos=(2, 2), size=(gFieldWidth, gFieldHeight)):
        wx.Panel.__init__(self, parent, pos=pos, size=size)
        self.pos = pos
        self.size = size

        self.SetBackgroundColour(gFieldColor)
        self.SetBackgroundStyle(wx.BG_STYLE_PAINT)
        
        self.bar = Bar(self, gBarIniPos[0], gBarIniPos[1])
        self.ball = Ball(self, gBarIniPos[0], (gBarIniPos[1] - gBallRadius))
        self.blocks = [[Block(i*gBlkSize[0], gBlkTop+j*gBlkSize[1], \
                              gBlkColor[(gBlkVCnt*j+i)%gBlkHCnt]) \
                        for i in range(gBlkVCnt)] for j in range(gBlkHCnt)]
        self.block_exist = [[1 for i in range(gBlkVCnt)] for j in range(gBlkHCnt)]
        self.state = gGameState[0]

        self.Bind(wx.EVT_PAINT, self.onPaint)
        self.Bind(wx.EVT_KEY_DOWN, self.onKey)

    def update(self):
        self.ball.move()
        self.Refresh()
    
    def onPaint(self, event):
        dc = wx.AutoBufferedPaintDC(self)
        dc.Clear()
        # Paint Bar
        dc.SetPen(wx.Pen(self.bar.color))
        dc.SetBrush(wx.Brush(self.bar.color))
        dc.DrawRectangle(self.bar.x, self.bar.y, self.bar.size[0], self.bar.size[1])
        # Paint Ball
        dc.SetPen(wx.Pen(self.ball.color))
        dc.SetBrush(wx.Brush(self.ball.color))
        dc.DrawCircle(self.ball.x, self.ball.y, self.ball.radius)
        # Paint Blovks
        for (i, b_list) in enumerate(self.blocks):
            for (j, b) in enumerate(b_list):
                if self.block_exist[i][j] == 1:
                    dc.SetPen(wx.Pen(b.color,1))
                    dc.SetBrush(wx.Brush(b.color))
                    dc.DrawRectangle(b.x, b.y, b.size[0], b.size[1])

    def onKey(self, event):
        keycode = event.GetKeyCode()
        if keycode == wx.WXK_SPACE:
            if self.state == "INIT":
                self.ball.shoot()
                self.state = gGameState[1]
            elif self.state == "END":
                self.initialize()
                self.state = gGameState[0]
        elif (keycode == wx.WXK_LEFT or keycode == ord('H')) and self.state != "END":
            self.bar.move(-1)
        elif (keycode == wx.WXK_RIGHT or keycode == ord('L')) and self.state != "END":
            self.bar.move(1)

    def initialize(self):
        self.bar.x = gBarIniPos[0]
        self.bar.y = gBarIniPos[1]
        self.ball.x = self.bar.x
        self.ball.y = self.bar.y - self.ball.radius
        self.ball.vec = [0, 0]
        self.block_exist = [[1 for i in range(gBlkVCnt)] for j in range(gBlkHCnt)]


class Bar(object):
    def __init__(self, parent, x, y, size=gBarSize, color=gBarColor, speed=gBarSpeed):
        self.parent = parent
        self.x = x
        self.y = y
        self.size = size
        self.color = color
        self.speed = speed

    def move(self, direction):
        if direction >= 0:
            self.x += self.speed
        elif direction < 0:
            self.x -= self.speed

        if self.x < self.parent.pos[0]:
            self.x = self.parent.pos[0]
        elif self.x > (self.parent.pos[0] + self.parent.size[0] - self.size[0]):
            self.x = self.parent.pos[0] + self.parent.size[0] - self.size[0]


class Ball(object):
    def __init__(self, parent, x, y, radius=gBallRadius, vec=[0.0,0.0], \
                 color=gBallColor, speed=gIniBallSpeed):
        self.parent = parent
        self.x = x
        self.y = y
        self.radius = radius
        self.vec = vec
        self.color = color
        self.speed = speed

    def shoot(self):
        self.parent.state = gGameState[1]
        rand_x = random.randrange(1000, 5000)
        rand_y = random.randrange(2000, 5000)
        self.vec = (-1.0 * float(rand_x)/1000.0, -1.0 * float(rand_y)/1000.0)
        pass

    def move(self):
        if self.parent.state == "INIT":
            self.x = self.parent.bar.x
            self.y = self.parent.bar.y - self.radius
        elif self.parent.state == "END":
            pass
        else:
            unit = self.speed / math.sqrt(pow(self.vec[0],2) + pow(self.vec[1],2))
            self.x += (self.vec[0] * unit)
            self.y += (self.vec[1] * unit)
            self.collision()

    def collision(self):
        # Game Over
        if (self.y + self.radius) >= self.parent.size[1]:
            self.parent.state = gGameState[2]
            return
        
        # Bound at Bar
        if self.x >= self.parent.bar.x and \
           self.x <= (self.parent.bar.x + self.parent.bar.size[0]) and \
           self.y >= (self.parent.bar.y - self.radius) and \
           self.y <  (self.parent.bar.y + self.radius) and \
           self.vec[1] > 0:

            self.vec = [self.vec[0], -1*self.vec[1]]
            return

        # Bound at Frame
        #### left
        if self.vec[0] < 0 and \
           self.x <= (self.parent.pos[0] + self.radius):
            self.vec = [-1*self.vec[0], self.vec[1]]
            return
        #### right
        if self.vec[0] > 0 and \
           self.x >= (self.parent.pos[0] + self.parent.size[0] - self.radius):
            self.vec = [-1*self.vec[0], self.vec[1]]
            return
        
        #### ceiling 
        if self.y <= (self.parent.pos[1] + self.radius):
            self.vec = [self.vec[0], -1*self.vec[1]]
            return

        # Bound at Blocks
        no_block = 1
        for (i, b_exist_list) in enumerate(self.parent.block_exist):
            for (j, b_exist) in enumerate(b_exist_list):
                if b_exist == 1:
                    no_block = 0
                    tgt_block = self.parent.blocks[i][j]
                    # Ball cross the block edge
                    if self.x > (tgt_block.x - self.radius) and \
                       self.x < (tgt_block.x + tgt_block.size[0] + self.radius) and \
                       self.y > (tgt_block.y - self.radius) and \
                       self.y < (tgt_block.y + tgt_block.size[1] + self.radius):

                        self.parent.block_exist[i][j] = 0
                        # update vec
                        x0 = tgt_block.x + tgt_block.size[0] / 2
                        y0 = tgt_block.y + tgt_block.size[1] / 2
                        k = float(tgt_block.size[1]) / float(tgt_block.size[0])
                        #### top
                        if (self.vec[1] > 0) and \
                           (self.x < x0 and \
                            self.y < (k * (self.x - x0) + y0 - self.radius)) or \
                           (self.x > x0 and \
                            self.y < (-1 * k * (self.x - x0) + y0 - self.radius)):

                            self.vec = [self.vec[0], -1*self.vec[1]]
                        #### bottom
                        elif (self.vec[1] < 0) and \
                             (self.x < x0 and \
                              self.y > (-1 * k * (self.x - x0) + y0 + self.radius)) or \
                             (self.x > x0 and \
                              self.y > (k * (self.x - x0) + y0 + self.radius)):

                            self.vec = [self.vec[0], -1*self.vec[1]]
                        #### left
                        elif (self.vec[0] > 0) and (self.x < x0):
                            self.vec = [-1*self.vec[0], self.vec[1]]
                        ### right
                        elif (self.vec[0] < 0) and (self.x > x0):
                            self.vec = [-1*self.vec[0], self.vec[1]]

                        return

        if no_block == 1:
            # Game Clear
            self.parent.state = gGameState[2]


class Block(object):
    def __init__(self, x, y, color, size=gBlkSize):
        self.x = x
        self.y = y
        self.color = color
        self.size = size


if __name__ == "__main__":
    app = wx.App()
    frame = MainFrame().Show()
    app.MainLoop()


Environnement de contrôle de fonctionnement

Je pense que wxpython fonctionnera également avec 2.8.

comment jouer

break-wall.png

référence

Recommended Posts

Faisons une rupture de bloc avec wxPython
Faisons Othello avec wxPython
Faisons une interface graphique avec python.
Faisons un graphe avec python! !!
Faisons un spacon avec xCAT
Faisons un jeu de shiritori avec Python
Faisons la voix lentement avec Python
Faisons un langage simple avec PLY 1
Créez un framework Web avec Python! (1)
Faisons une IA à trois yeux avec Pylearn 2
Faisons un bot Twitter avec Python!
Créez un framework Web avec Python! (2)
Remplaçons UWSC par Python (5) Faisons un robot
Faisons un robot Discord.
Faites une loterie avec Python
Faire un feu avec kdeplot
[Jouons avec Python] Créer un livre de comptes de ménage
Essayez de créer un jeu simple avec Python 3 et iPhone
Facilitons un peu la gestion des dépendances avec pip
Créons une application Mac avec Tkinter et py2app
Essayez de créer une grille sphérique avec Rhinoceros / Grasshopper / GHPython
[Super facile] Faisons un LINE BOT avec Python.
Créons un client de socket Web avec Python. (Authentification par jeton d'accès)
Faisons une rumba distante [Logiciel]
Faisons un service de vente au comptant 2
Faisons un service de vente au comptant 1
Faisons l'IA d'Othello avec Chainer-Part 1-
Créer un système de recommandation avec python
Créer un filtre avec un modèle django
Faisons l'IA d'Othello avec Chainer-Part 2-
Créer un itérateur de modèle avec PySide
Faire un joli graphique avec plotly
Faisons un diagramme sur lequel on peut cliquer avec IPython
Faisons un service de vente au comptant 3
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 1
Faisons un ordinateur de vélo avec Raspberry Pi Zero (W, WH)
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 2
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 3
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 4
Faisons une discussion WEB en utilisant WebSocket avec AWS sans serveur (Python)!
Créer un lecteur vidéo avec PySimpleGUI + OpenCV
Créons un groupe gratuit avec Python
Créez un simulateur de gacha rare avec Flask
Créez un pipeline de notebook avec Kedro + Papermill
Faire une figure partiellement zoomée avec matplotlib
Raclons un site dynamique avec Docker
Créez un quiz de dessin avec kivy + PyTorch
Créez un classificateur en cascade avec Google Colaboratory
[Python] Rendons matplotlib compatible avec le japonais
Faire un circuit logique avec Perceptron (Perceptron multicouche)
Faire Oui Non Popup avec Kivy
Faisons un site multilingue en utilisant flask-babel
Faire une minuterie de lavage-séchage avec Raspberry Pi
Créer une animation GIF avec surveillance des dossiers
Faisons un calcul de combinaison avec Python
Créez une application de bureau avec Python avec Electron
Faisons un plug-in backend pour Errbot
[Ev3dev] Faisons un programme de contrôle à distance par Python avec le protocole RPyC
Casser des blocs avec Tensorflow