Machen wir einen Blockbruch mit wxPython

Einführung

Ein Video von Google Deepmind, das Deep Q Learning auf ATARIs Break Out anwendet, um es zu erfassen, ist populär geworden. (Das Video ist hier) Ich beschloss, dies selbst zu versuchen, und dachte, es wäre später nützlich, also begann ich damit, selbst einen Blockbrecher zu bauen. Der Grund, warum ich wxPython verwendet habe, war, dass ich wollte, dass die Deep Learning-Bibliothek später Python-basiert ist.

Bis Deep Q Learning ist es noch ein langer Weg, aber ich habe einen Artikel geschrieben, in der Hoffnung, dass er beim Erstellen von Animations-Apps mit wxPython hilfreich sein könnte.

Es erfordert wxPython, um zu funktionieren. Die Installationsmethode lautet [hier](http://qiita.com/kanlkan/items/5e6f2e63de406f46b3b1#wxpython%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83 Siehe% 88% E3% 83% BC% E3% 83% AB) und so weiter.

Quellcode

Es ist auch auf GitHub veröffentlicht, aber es ist nicht so lang, also werde ich es auch hier veröffentlichen.

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()


Betriebsüberprüfungsumgebung

Ich denke, wxpython wird auch mit 2.8 funktionieren.

Spielanleitung

break-wall.png

Referenz

Recommended Posts

Machen wir einen Blockbruch mit wxPython
Machen wir Othello mit wxPython
Lassen Sie uns eine GUI mit Python erstellen.
Lassen Sie uns ein Diagramm mit Python erstellen! !!
Machen wir mit xCAT einen Spacon
Lassen Sie uns mit Python ein Shiritori-Spiel machen
Lassen Sie uns mit Python langsam sprechen
Lassen Sie uns mit PLY 1 eine einfache Sprache erstellen
Erstellen Sie ein Webframework mit Python! (1)
Machen wir mit Pylearn 2 eine dreiäugige KI
Machen wir einen Twitter-Bot mit Python!
Erstellen Sie ein Webframework mit Python! (2)
Ersetzen wir UWSC durch Python (5) Machen wir einen Roboter
Machen wir einen Discord Bot.
Machen Sie eine Lotterie mit Python
Machen Sie ein Feuer mit kdeplot
[Lass uns mit Python spielen] Ein Haushaltsbuch erstellen
Versuchen Sie, ein einfaches Spiel mit Python 3 und iPhone zu erstellen
Lassen Sie uns das Abhängigkeitsmanagement mit pip etwas einfacher machen
Lassen Sie uns eine Mac-App mit Tkinter und py2app erstellen
Versuchen Sie, mit Rhinoceros / Grasshopper / GHPython ein sphärisches Gitter zu erstellen
[Super einfach] Machen wir einen LINE BOT mit Python.
Lassen Sie uns mit Python einen Web-Socket-Client erstellen. (Zugriffstoken-Authentifizierung)
Lassen Sie uns eine Remote-Rumba erstellen [Software]
Machen wir einen Spot Sale Service 2
Machen wir einen Spot Sale Service 1
Machen wir Othellos KI mit Chainer-Teil 1-
Erstellen Sie ein Empfehlungssystem mit Python
Machen Sie einen Filter mit einer Django-Vorlage
Machen wir Othellos KI mit Chainer-Teil 2-
Erstellen Sie mit PySide einen Modelliterator
Machen Sie eine schöne Grafik mit Plotly
Lassen Sie uns ein Diagramm erstellen, auf das mit IPython geklickt werden kann
Machen wir einen Spot Sale Service 3
Lassen Sie uns eine WEB-Anwendung für das Telefonbuch mit Flasche Teil 1 erstellen
Machen wir einen Fahrradcomputer mit Raspberry Pi Zero (W, WH)
Lassen Sie uns eine WEB-Anwendung für das Telefonbuch mit Flasche Teil 2 erstellen
Lassen Sie uns eine WEB-Anwendung für das Telefonbuch mit Flasche Teil 3 erstellen
Lassen Sie uns eine WEB-Anwendung für das Telefonbuch mit Flasche Teil 4 erstellen
Lassen Sie uns einen Web-Chat mit WebSocket mit AWS serverless (Python) durchführen!
Erstellen Sie einen Videoplayer mit PySimpleGUI + OpenCV
Erstellen wir mit Python eine kostenlose Gruppe
Machen Sie einen seltenen Gacha-Simulator mit Flask
Erstellen Sie eine Notebook-Pipeline mit Kedro + Papermill
Machen Sie mit matplotlib eine teilweise gezoomte Figur
Lassen Sie uns mit Docker eine dynamische Site kratzen
Machen Sie ein Zeichnungsquiz mit kivy + PyTorch
Erstellen Sie einen Kaskadenklassifizierer mit Google Colaboratory
[Python] Lassen Sie uns matplotlib mit Japanisch kompatibel machen
Machen Sie eine Logikschaltung mit Perceptron (Multilayer Perceptron)
Machen Sie Ja Nein Popup mit Kivy
Lassen Sie uns mit flask-babel eine mehrsprachige Site erstellen
Machen Sie einen Waschtrocknungs-Timer mit Raspberry Pi
Erstellen Sie eine GIF-Animation mit Ordnerüberwachung
Lassen Sie uns eine Kombinationsberechnung mit Python durchführen
Erstellen Sie eine Desktop-App mit Python mit Electron
Lassen Sie uns ein Backend-Plug-In für Errbot erstellen
[Ev3dev] Lassen Sie uns ein Fernsteuerungsprogramm von Python mit dem RPyC-Protokoll erstellen
Brechen Sie Blöcke mit Tensorflow