How to create a game for wxPython - Part 2 (Phoenix)

Keywords : Tic tac toe, Puzzle, 2048, Game, Pygame.


Demonstrating :

Tested py3.x, wx4.x and Win10.

Are you ready to use some samples ? ;)

Test, modify, correct, complete, improve and share your discoveries ! (!)


Tic Tac Toe

img_TicTacToe.png

   1 # tic_tac_toe.py
   2 
   3 """
   4 
   5 wxPython Tic Tac Toe game.
   6 
   7 Author : Mike Driscoll
   8 Link : https://www.blog.pythonlibrary.org/2013/07/30/wxpython-creating-a-simple-tic-tac-toe-game/
   9 
  10 """
  11 
  12 import random
  13 import wx
  14 import wx.lib.buttons as buttons
  15 
  16 # class TTTPanel
  17 # class TTTFrame
  18 
  19 #---------------------------------------------------------------------------
  20 
  21 class TTTPanel(wx.Panel):
  22     """
  23     Tic-Tac-Toe Panel object.
  24     """
  25     def __init__(self, parent):
  26         """
  27         Initialize the panel.
  28         """
  29         wx.Panel.__init__(self, parent)
  30 
  31         #------------
  32 
  33         self.toggled = False
  34         self.playerWon = False
  35 
  36         #------------
  37 
  38         self.LayoutWidgets()
  39 
  40     #-----------------------------------------------------------------------
  41 
  42     def CheckWin(self, computer=False):
  43         """
  44         Check if the player won.
  45         """
  46 
  47         for button1, button2, button3 in self.methodsToWin:
  48             if button1.GetLabel() == button2.GetLabel() and \
  49                button2.GetLabel() == button3.GetLabel() and \
  50                button1.GetLabel() != "":
  51                 print("Player wins !")
  52                 self.playerWon = True
  53                 button1.SetBackgroundColour("Yellow")
  54                 button2.SetBackgroundColour("Yellow")
  55                 button3.SetBackgroundColour("Yellow")
  56                 self.Layout()
  57 
  58                 if not computer:
  59                     msg = "You Won ! Would you like to play again ?"
  60                     dlg = wx.MessageDialog(None, msg, "Winner !",
  61                                            wx.YES_NO | wx.ICON_WARNING)
  62                     result = dlg.ShowModal()
  63                     if result == wx.ID_YES:
  64                         wx.CallAfter(self.Restart)
  65                     dlg.Destroy()
  66                     break
  67                 else:
  68                     return True
  69 
  70 
  71     def LayoutWidgets(self):
  72         """
  73         Create and layout the widgets.
  74         """
  75 
  76         mainSizer = wx.BoxSizer(wx.VERTICAL)
  77         self.fgSizer = wx.FlexGridSizer(rows=3, cols=3, vgap=5, hgap=5)
  78         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  79 
  80         #------------
  81 
  82         font = wx.Font(22, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
  83                        wx.FONTWEIGHT_BOLD)
  84 
  85         size = (100,100)
  86         self.button1 = buttons.GenToggleButton(self, size=size, name="btn1")
  87         self.button2 = buttons.GenToggleButton(self, size=size, name="btn2")
  88         self.button3 = buttons.GenToggleButton(self, size=size, name="btn3")
  89         self.button4 = buttons.GenToggleButton(self, size=size, name="btn4")
  90         self.button5 = buttons.GenToggleButton(self, size=size, name="btn5")
  91         self.button6 = buttons.GenToggleButton(self, size=size, name="btn6")
  92         self.button7 = buttons.GenToggleButton(self, size=size, name="btn7")
  93         self.button8 = buttons.GenToggleButton(self, size=size, name="btn8")
  94         self.button9 = buttons.GenToggleButton(self, size=size, name="btn9")
  95         self.normalBtnColour = self.button1.GetBackgroundColour()
  96 
  97         self.widgets = [self.button1, self.button2, self.button3,
  98                         self.button4, self.button5, self.button6,
  99                         self.button7, self.button8, self.button9]
 100 
 101         # Change all the main game buttons' font and bind them to an event.
 102         for button in self.widgets:
 103             button.SetFont(font)
 104             button.Bind(wx.EVT_BUTTON, self.OnToggle)
 105 
 106         #------------
 107 
 108         # Add the widgets to the sizers.
 109         self.fgSizer.AddMany(self.widgets)
 110         mainSizer.Add(self.fgSizer, 0, wx.ALL|wx.CENTER, 5)
 111 
 112         self.endTurnBtn = wx.Button(self, label="End Turn")
 113         self.endTurnBtn.Bind(wx.EVT_BUTTON, self.OnEndTurn)
 114         self.endTurnBtn.Disable()
 115         btnSizer.Add(self.endTurnBtn, 0, wx.ALL|wx.CENTER, 5)
 116 
 117         startOverBtn = wx.Button(self, label="Restart")
 118         startOverBtn.Bind(wx.EVT_BUTTON, self.OnRestart)
 119         btnSizer.Add(startOverBtn, 0, wx.ALL|wx.CENTER, 5)
 120         mainSizer.Add(btnSizer, 0, wx.CENTER)
 121 
 122         self.methodsToWin = [(self.button1, self.button2, self.button3),
 123                              (self.button4, self.button5, self.button6),
 124                              (self.button7, self.button8, self.button9),
 125                              # Vertical ways to win.
 126                              (self.button1, self.button4, self.button7),
 127                              (self.button2, self.button5, self.button8),
 128                              (self.button3, self.button6, self.button9),
 129                              # Diagonal ways to win.
 130                              (self.button1, self.button5, self.button9),
 131                              (self.button3, self.button5, self.button7)]
 132 
 133         #------------
 134 
 135         self.SetSizer(mainSizer)
 136 
 137 
 138     def EnableUnusedButtons(self):
 139         """
 140         Re-enable unused buttons.
 141         """
 142 
 143         for button in self.widgets:
 144             if button.GetLabel() == "":
 145                 button.Enable()
 146         self.Refresh()
 147         self.Layout()
 148 
 149 
 150     def OnEndTurn(self, event):
 151         """
 152         Let the computer play.
 153         """
 154 
 155         # Rest toggled flag state.
 156         self.toggled = False
 157 
 158         # Disable all played buttons.
 159         for btn in self.widgets:
 160             if btn.GetLabel():
 161                 btn.Disable()
 162 
 163         computerPlays = []
 164         noPlays = []
 165 
 166         for button1, button2, button3 in self.methodsToWin:
 167             if button1.GetLabel() == button2.GetLabel() and button3.GetLabel() == "":
 168                 if button1.GetLabel() == "" and button2.GetLabel() == "" and button1.GetLabel() == "":
 169                     pass
 170                 else:
 171                     #if button1.GetLabel() == "O":
 172                     noPlays.append(button3)
 173 
 174             elif button1.GetLabel() == button3.GetLabel() and button2.GetLabel() == "":
 175                 if button1.GetLabel() == "" and button2.GetLabel() == "" and button1.GetLabel() == "":
 176                     pass
 177                 else:
 178                     noPlays.append(button2)
 179 
 180             elif button2.GetLabel() == button3.GetLabel() and button1.GetLabel() == "":
 181                 if button1.GetLabel() == "" and button2.GetLabel() == "" and button1.GetLabel() == "":
 182                     pass
 183                 else:
 184                     noPlays.append(button1)
 185 
 186             noPlays = list(set(noPlays))
 187 
 188             if button1.GetLabel() == "" and button1 not in noPlays:
 189                 if not self.CheckWin(computer=True):
 190                     computerPlays.append(button1)
 191 
 192             if button2.GetLabel() == "" and button2 not in noPlays:
 193                 if not self.CheckWin(computer=True):
 194                     computerPlays.append(button2)
 195 
 196             if button3.GetLabel() == "" and button3 not in noPlays:
 197                 if not self.CheckWin(computer=True):
 198                     computerPlays.append(button3)
 199 
 200 
 201         computerPlays = list(set(computerPlays))
 202         print(noPlays)
 203         choices = len(computerPlays)
 204         while 1 and computerPlays:
 205             btn = random.choice(computerPlays)
 206 
 207             if btn not in noPlays:
 208                 print(btn.GetName())
 209                 btn.SetLabel("O")
 210                 btn.Disable()
 211                 break
 212             else:
 213                 print("Removed => " + btn.GetName())
 214                 computerPlays.remove(btn)
 215             if choices < 1:
 216                 self.GiveUp()
 217                 break
 218             choices -= 1
 219         else:
 220             # Computer cannot play without winning.
 221             self.GiveUp()
 222 
 223         self.endTurnBtn.Disable()
 224         self.EnableUnusedButtons()
 225 
 226 
 227     def GiveUp(self):
 228         """
 229         The computer cannot find a way to play that
 230         lets the user win, so it gives up.
 231         """
 232 
 233         msg = "I give up, Dave. You're too good at this game !"
 234         dlg = wx.MessageDialog(None, msg, "Game Over !",
 235                                wx.YES_NO | wx.ICON_WARNING)
 236 
 237         result = dlg.ShowModal()
 238         if result == wx.ID_YES:
 239             self.Restart()
 240         else:
 241             wx.CallAfter(self.GetParent().Close)
 242         dlg.Destroy()
 243 
 244 
 245     def OnRestart(self, event):
 246         """
 247         Calls the Restart method.
 248         """
 249 
 250         self.Restart()
 251 
 252 
 253     def OnToggle(self, event):
 254         """
 255         On button toggle, change the label of the button
 256         pressed and disable the other buttons unless the
 257         user changes their mind.
 258         """
 259 
 260         button = event.GetEventObject()
 261         button.SetLabel("X")
 262         button_id = button.GetId()
 263 
 264         self.CheckWin()
 265         if not self.toggled:
 266             self.toggled = True
 267             self.endTurnBtn.Enable()
 268             for btn in self.widgets:
 269                 if button_id != btn.GetId():
 270                     btn.Disable()
 271         else:
 272             self.toggled = False
 273             self.endTurnBtn.Disable()
 274             button.SetLabel("")
 275             self.EnableUnusedButtons()
 276 
 277         # Check if it's a "cats game" - no one's won.
 278         if not self.playerWon:
 279             labels = [True if btn.GetLabel() else False for btn in self.widgets]
 280             if False not in labels:
 281                 msg = "Cats Game - No one won ! Would you like to play again ?"
 282                 dlg = wx.MessageDialog(None, msg, "Game Over !",
 283                                        wx.YES_NO | wx.ICON_WARNING)
 284                 result = dlg.ShowModal()
 285                 if result == wx.ID_YES:
 286                     self.Restart()
 287                 dlg.Destroy()
 288 
 289 
 290     def Restart(self):
 291         """
 292         Restart the game and reset everything.
 293         """
 294         for button in self.widgets:
 295             button.SetLabel("")
 296             button.SetValue(False)
 297             button.SetBackgroundColour(self.normalBtnColour)
 298         self.toggled = False
 299         self.playerWon = False
 300         self.endTurnBtn.Disable()
 301         self.EnableUnusedButtons()
 302 
 303 #---------------------------------------------------------------------------
 304 
 305 class TTTFrame(wx.Frame):
 306     """
 307     Tic-Tac-Toe Frame object.
 308     """
 309     def __init__(self):
 310         """
 311         Constructor.
 312         """
 313         style = wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX
 314         wx.Frame.__init__(self, parent=None,
 315                           title="", size=(400, 400),
 316                           style=style)
 317 
 318         #------------
 319 
 320         self.SetIcon(wx.Icon(".\icons\wxwin.ico"))
 321         self.SetTitle("Tic-Tac-Toe")
 322 
 323         #------------
 324 
 325         panel = TTTPanel(self)
 326 
 327         #------------
 328 
 329         self.CenterOnScreen(wx.BOTH)
 330         self.Show()
 331 
 332 #---------------------------------------------------------------------------
 333 
 334 def main():
 335     app = wx.App(False)
 336     frame = TTTFrame()
 337     app.MainLoop()
 338 
 339 #---------------------------------------------------------------------------
 340 
 341 if __name__ == '__main__':
 342     main()


Puzzle

img_puzzle.png

   1 # puzzle.py
   2 
   3 """
   4 
   5 Author  : Jan Bodnar (Zetcode)
   6 Link : http://zetcode.com/wxpython/gripts/
   7 
   8 """
   9 
  10 import sys
  11 import os
  12 import wx
  13 import random
  14 
  15 # class MyFrame
  16 # class MyApp
  17 
  18 #---------------------------------------------------------------------------
  19 
  20 class MyFrame(wx.Dialog):
  21     """
  22     ...
  23     """
  24     def __init__(self, *args, **kw):
  25         super(MyFrame, self).__init__(*args, **kw)
  26 
  27         #------------
  28 
  29         # Return icons folder.
  30         self.icons_dir = wx.GetApp().GetIconsDir()
  31 
  32         #------------
  33 
  34         # Simplified init method.
  35         self.SetProperties()
  36         self.InitUI()
  37 
  38     #-----------------------------------------------------------------------
  39 
  40     def SetProperties(self):
  41         """
  42         ...
  43         """
  44 
  45         frameIcon = wx.Icon(os.path.join(self.icons_dir,
  46                                          "wxwin.ico"),
  47                             type=wx.BITMAP_TYPE_ICO)
  48         self.SetIcon(frameIcon)
  49 
  50 
  51     def InitUI(self):
  52         """
  53         ...
  54         """
  55 
  56         images = ['sid1.png', 'sid2.png', 'sid3.png', 'sid4.png',
  57                 'sid5.png', 'sid6.png', 'sid7.png', 'sid8.png']
  58 
  59         self.pos = [ [0, 1, 2], [3, 4, 5], [6, 7, 8] ]
  60 
  61         self.sizer = wx.GridSizer(3, 3, 0, 0)
  62 
  63         numbers = [0, 1, 2, 3, 4, 5, 6, 7]
  64         random.shuffle(numbers)
  65 
  66         for i in numbers:
  67 
  68                 btn = wx.BitmapButton(self, i, wx.Bitmap(images[i]))
  69                 btn.Bind(wx.EVT_BUTTON, self.OnPressButton, btn)
  70                 self.sizer.Add(btn)
  71 
  72         self.empty = wx.BitmapButton(self, bitmap=wx.Bitmap('empty.png'))
  73         self.empty.Bind(wx.EVT_BUTTON, self.OnPressButton, self.empty)
  74         self.sizer.Add(self.empty)
  75 
  76         self.SetSizerAndFit(self.sizer)
  77         self.SetTitle('Puzzle')
  78         self.Centre()
  79         self.ShowModal()
  80         self.Destroy()
  81 
  82 
  83     def OnPressButton(self, event):
  84         """
  85         ...
  86         """
  87 
  88         btn = event.GetEventObject()
  89 
  90         width = self.empty.GetSize().x
  91         height = self.empty.GetSize().y
  92 
  93         btnX = btn.GetPosition().x
  94         btnY = btn.GetPosition().y
  95         emptyX = self.empty.GetPosition().x
  96         emptyY = self.empty.GetPosition().y
  97 
  98 
  99         if (((btnX == emptyX) and (emptyY - btnY) == height)
 100           or ((btnX == emptyX) and (emptyY - btnY) == -height)
 101           or ((btnY == emptyY) and (emptyX - btnX) == width)
 102           or ((btnY == emptyY) and (emptyX - btnX) == -width)):
 103 
 104             self.ExchangeImages(btn)
 105 
 106 
 107     def ExchangeImages(self, btn):
 108         """
 109         ...
 110         """
 111 
 112         bmp1 = self.empty.GetBitmapLabel()
 113         bmp2 = btn.GetBitmapLabel()
 114 
 115         self.empty.SetBitmapLabel(bmp2)
 116         btn.SetBitmapLabel(bmp1)
 117 
 118         self.empty = btn
 119 
 120 #---------------------------------------------------------------------------
 121 
 122 class MyApp(wx.App):
 123     """
 124     ...
 125     """
 126     def OnInit(self):
 127 
 128         #------------
 129 
 130         self.installDir = os.path.split(os.path.abspath(sys.argv[0]))[0]
 131 
 132         #------------
 133 
 134         frame = MyFrame(None)
 135         self.SetTopWindow(frame)
 136         frame.Show(True)
 137 
 138         return True
 139 
 140     #-----------------------------------------------------------------------
 141 
 142     def GetInstallDir(self):
 143         """
 144         Returns the installation directory for my application.
 145         """
 146 
 147         return self.installDir
 148 
 149 
 150     def GetIconsDir(self):
 151         """
 152         Returns the icons directory for my application.
 153         """
 154 
 155         icons_dir = os.path.join(self.installDir, "icons")
 156         return icons_dir
 157 
 158 #---------------------------------------------------------------------------
 159 
 160 def main():
 161     app = MyApp(False)
 162     app.MainLoop()
 163 
 164 #---------------------------------------------------------------------------
 165 
 166 if __name__ == "__main__" :
 167     main()


2048

img_2048.png

   1 # -*- coding: utf-8 -*-
   2 
   3 # 2048.py
   4 
   5 """
   6 
   7 Author : Guolz
   8 version : 1.0.1
   9 Link : https://blog.csdn.net/weixin_33709364/article/details/94581016
  10 
  11 """
  12 
  13 # Importing libraries to be used
  14 import wx
  15 import os
  16 import random
  17 import copy
  18 
  19 #---------------------------------------------------------------------------
  20 
  21 # Creating the user interface frame that the user will interact
  22 # with and perform actions that will have an appropriate response
  23 class Frame(wx.Frame):
  24     def __init__(self,title):
  25         # Created a default toolbar of application with a resizeable option and minimize box
  26         super(Frame,self).__init__(None,-1,title,
  27                 style=wx.DEFAULT_FRAME_STYLE^wx.MAXIMIZE_BOX^wx.RESIZE_BORDER)
  28 
  29         # Setting different colours for each tile in the game
  30         self.colors = {0:(204,192,179),2:(238, 228, 218),4:(237, 224, 200),
  31                 8:(242, 177, 121),16:(245, 149, 99),32:(246, 124, 95),
  32                 64:(246, 94, 59),128:(237, 207, 114),256:(237, 207, 114),
  33                 512:(237, 207, 114),1024:(237, 207, 114),2048:(237, 207, 114),
  34                 4096:(237, 207, 114),8192:(237, 207, 114),16384:(237, 207, 114),
  35                 32768:(237, 207, 114),65536:(237, 207, 114),131072:(237, 207, 114),
  36                 262144:(237, 207, 114),524288:(237, 207, 114),1048576:(237, 207, 114),
  37                 2097152:(237, 207, 114),4194304:(237, 207, 114),
  38                 8388608:(237, 207, 114),16777216:(237, 207, 114),
  39                 33554432:(237, 207, 114),67108864:(237, 207, 114),
  40                 134217728:(237, 207, 114),268435456:(237, 207, 114),
  41                 536870912:(237, 207, 114),1073741824:(237, 207, 114),
  42                 2147483648:(237, 207, 114),4294967296:(237, 207, 114),
  43                 8589934592:(237, 207, 114),17179869184:(237, 207, 114),
  44                 34359738368:(237, 207, 114),68719476736:(237, 207, 114),
  45                 137438953472:(237, 207, 114),274877906944:(237, 207, 114),
  46                 549755813888:(237, 207, 114),1099511627776:(237, 207, 114),
  47                 2199023255552:(237, 207, 114),4398046511104:(237, 207, 114),
  48                 8796093022208:(237, 207, 114),17592186044416:(237, 207, 114),
  49                 35184372088832:(237, 207, 114),70368744177664:(237, 207, 114),
  50                 140737488355328:(237, 207, 114),281474976710656:(237, 207, 114),
  51                 562949953421312:(237, 207, 114),1125899906842624:(237, 207, 114),
  52                 2251799813685248:(237, 207, 114),4503599627370496:(237, 207, 114),
  53                 9007199254740992:(237, 207, 114),18014398509481984:(237, 207, 114),
  54                 36028797018963968:(237, 207, 114),72057594037927936:(237, 207, 114)}
  55 
  56         # Initalize game
  57         self.setIcon()
  58         self.initGame()
  59 
  60         # Displays game and provides settings to move the tiles
  61         panel = wx.Panel(self)
  62         panel.SetBackgroundColour("#faf8ef")
  63         panel.Bind(wx.EVT_KEY_DOWN,self.onKeyDown)
  64         panel.SetFocus()
  65         self.initBuffer()
  66         self.Bind(wx.EVT_SIZE,self.onSize)
  67         self.Bind(wx.EVT_PAINT, self.onPaint)
  68         self.Bind(wx.EVT_CLOSE,self.onClose)
  69         self.SetClientSize((505,720))
  70         self.Center()
  71         self.Show()
  72 
  73     #-----------------------------------------------------------------------
  74 
  75     # Puts on board so user can see
  76     def onPaint(self,event):
  77         dc = wx.BufferedPaintDC(self,self.buffer)
  78 
  79 
  80     # Saves score and terminates when closed
  81     def onClose(self,event):
  82         self.saveScore()
  83         self.Destroy()
  84 
  85 
  86     # Putting icon on toolbar
  87     def setIcon(self):
  88         icon = wx.Icon(".\icons\wxwin.ico",wx.BITMAP_TYPE_ICO)
  89         self.SetIcon(icon)
  90 
  91 
  92     # Opens previous game and loads and updates score
  93     def loadScore(self):
  94         if os.path.exists("bestscore.ini"):
  95             ff = open("bestscore.ini")
  96             self.bstScore = ff.read()
  97             ff.close()
  98 
  99 
 100     # Saves score and writes to file so it may be opened later
 101     def saveScore(self):
 102         ff = open("bestscore.ini","w")
 103         ff.write(str(self.bstScore))
 104         ff.close()
 105 
 106 
 107     # Initalize game so when it opens it displays text, score and all data needed for the game
 108     def initGame(self):
 109         self.bgFont = wx.Font(50,wx.SWISS,wx.NORMAL,wx.BOLD)
 110         self.scFont = wx.Font(36,wx.SWISS,wx.NORMAL,wx.BOLD)
 111         self.smFont = wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL)
 112         self.curScore = 0
 113         self.bstScore = 0
 114         self.loadScore()
 115         # 4 rows and 4 coloums for tiles ( using arrays because it easily represents system used )
 116         self.data = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
 117         count = 0
 118         # First 2 tile inialized if 1 tile it must be 2 but if 2 tiles connected then its 4
 119         while count<2:
 120             row = random.randint(0,len(self.data)-1)
 121             col = random.randint(0,len(self.data[0])-1)
 122             if self.data[row][col]!=0: continue
 123             self.data[row][col] = 2 if random.randint(0,1) else 4
 124             count += 1
 125 
 126     # Empty bitmap to put pixels in for game
 127     def initBuffer(self):
 128         w,h = self.GetClientSize()
 129         self.buffer = wx.Bitmap(w,h)
 130 
 131 
 132     # Displays all drawings to the screen
 133     def onSize(self,event):
 134         self.initBuffer()
 135         self.drawAll()
 136         # Placing tiles on screen and multiplying by 2 if 2 tiles
 137         # interact with one another(game logic)
 138 
 139 
 140     def putTile(self):
 141         available = []
 142         for row in range(len(self.data)):
 143             for col in range(len(self.data[0])):
 144                 if self.data[row][col]==0: available.append((row,col)) # Add tile if empty square
 145         if available:
 146             row,col = available[random.randint(0,len(available)-1)]
 147             self.data[row][col] = 2 if random.randint(0,1) else 4
 148             return True
 149         return False
 150 
 151 
 152     def update(self,vlist,direct): # Updates score and game tiles
 153         score = 0
 154         if direct: # Up or left
 155             i = 1
 156             while i<len(vlist):
 157                 # If 2 tiles of equal value mesh upward it multiples the
 158                 # values and deletes the ith number (2 squares = 1 square)
 159                 if vlist[i-1]==vlist[i]:
 160                     del vlist[i]
 161                     vlist[i-1] *= 2
 162                     score += vlist[i-1] # Adds multiplied value to score
 163                     i += 1
 164                 i += 1
 165         else:
 166             # Direction moved downward same thing as above but different direction
 167             i = len(vlist)-1
 168             while i>0:
 169                 if vlist[i-1]==vlist[i]:
 170                     del vlist[i]
 171                     vlist[i-1] *= 2
 172                     score += vlist[i-1]
 173                     i -= 1
 174                 i -= 1
 175         return score
 176 
 177 
 178     # The calucation and keeping logs of data for score (upward and downward movements)
 179     def slideUpDown(self,up):
 180         score = 0
 181         numCols = len(self.data[0])
 182         numRows = len(self.data)
 183         oldData = copy.deepcopy(self.data)
 184 
 185         for col in range(numCols):
 186             cvl = [self.data[row][col] for row in range(numRows) if self.data[row][col]!=0]
 187             if len(cvl)>=2:
 188                 score += self.update(cvl,up)
 189             for i in range(numRows-len(cvl)):
 190                 if up: cvl.append(0)
 191                 else: cvl.insert(0,0)
 192             for row in range(numRows): self.data[row][col] = cvl[row]
 193         return oldData!=self.data,score
 194 
 195 
 196     # The calucation and keeping logs of data for score (right and left movements)
 197     def slideLeftRight(self,left):
 198         score = 0
 199         numRows = len(self.data)
 200         numCols = len(self.data[0])
 201         oldData = copy.deepcopy(self.data)
 202 
 203         for row in range(numRows):
 204             rvl = [self.data[row][col] for col in range(numCols) if self.data[row][col]!=0]
 205             if len(rvl)>=2:
 206                 score += self.update(rvl,left)
 207             for i in range(numCols-len(rvl)):
 208                 if left: rvl.append(0)
 209                 else: rvl.insert(0,0)
 210             for col in range(numCols): self.data[row][col] = rvl[col]
 211         return oldData!=self.data,score
 212 
 213 
 214     def isGameOver(self):
 215         copyData = copy.deepcopy(self.data)
 216 
 217         # Tile is not moveable or you have lost if all tiles cant
 218         # move any pieces up,down, left or right
 219         flag = False
 220         if not self.slideUpDown(True)[0] and not self.slideUpDown(False)[0] and \
 221                 not self.slideLeftRight(True)[0] and not self.slideLeftRight(False)[0]:
 222             flag = True # Continue playing and copydata
 223         if not flag: self.data = copyData
 224         return flag
 225 
 226 
 227     # Game logic to see if you can make a move or end the game
 228     def doMove(self,move,score):
 229         # If you can move put a tile and update change
 230         if move:
 231             self.putTile()
 232             self.drawChange(score)
 233             # If game is over put a message box and update best score if its the new best score
 234             if self.isGameOver():
 235                 if wx.MessageBox(u"Game over", "Do you want to start over ?",
 236                                  wx.YES_NO|wx.ICON_INFORMATION==wx.YES):
 237                     bstScore = str(self.bstScore)
 238                     self.initGame()
 239                     self.bstScore = bstScore
 240                     self.drawAll()
 241 
 242 
 243     # When you click a directon for the tile to move, it moves in the appropriate direction
 244     def onKeyDown(self,event):
 245         keyCode = event.GetKeyCode()
 246 
 247         # if keyCode==wx.WXK_UP:
 248         if keyCode == ord('Z') or keyCode == ord('z'):
 249             self.doMove(*self.slideUpDown(True))
 250         # elif keyCode==wx.WXK_DOWN:
 251         elif keyCode == ord('S') or keyCode == ord('s'):
 252             self.doMove(*self.slideUpDown(False))
 253         # elif keyCode==wx.WXK_LEFT:
 254         elif keyCode == ord('Q') or keyCode == ord('q'):
 255             self.doMove(*self.slideLeftRight(True))
 256         # elif keyCode==wx.WXK_RIGHT:
 257         elif keyCode == ord('D') or keyCode == ord('d'):
 258             self.doMove(*self.slideLeftRight(False))
 259 
 260 
 261     # Creates background for the game board
 262     def drawBg(self,dc):
 263         dc.SetBackground(wx.Brush((250,248,239)))
 264         dc.Clear()
 265         dc.SetBrush(wx.Brush((187,173,160)))
 266         dc.SetPen(wx.Pen((187,173,160)))
 267         dc.DrawRoundedRectangle(15,150,475,475,5)
 268 
 269 
 270     # Creates a 2048 logo
 271     def drawLogo(self,dc):
 272         dc.SetFont(self.bgFont)
 273         dc.SetTextForeground((119,110,101))
 274         dc.DrawText(u"2048",15,26)
 275 
 276 
 277     # Provides text to screen (Chinese text)
 278     def drawLabel(self,dc):
 279         dc.SetFont(self.smFont)
 280         dc.SetTextForeground((119,110,101))
 281         dc.DrawText(u"Combine the same numbers,Get 2048 !",15,114)
 282         dc.DrawText(u"How to play : \nUse : (z) Up, (s) Down, (q) Left and (d) Right keys to move the square. \
 283                 \nWhen two squares of the same number meet,Will make one !",15,639)
 284 
 285 
 286     # Displays score to screen
 287     def drawScore(self,dc):
 288         dc.SetFont(self.smFont)
 289         scoreLabelSize = dc.GetTextExtent(u"SCORE")
 290         bestLabelSize = dc.GetTextExtent(u"BEST")
 291         curScoreBoardMinW = 15*2+scoreLabelSize[0]
 292         bstScoreBoardMinW = 15*2+bestLabelSize[0]
 293         curScoreSize = dc.GetTextExtent(str(self.curScore))
 294         bstScoreSize = dc.GetTextExtent(str(self.bstScore))
 295         curScoreBoardNedW = 10+curScoreSize[0]
 296         bstScoreBoardNedW = 10+bstScoreSize[0]
 297         curScoreBoardW = max(curScoreBoardMinW,curScoreBoardNedW)
 298         bstScoreBoardW = max(bstScoreBoardMinW,bstScoreBoardNedW)
 299         dc.SetBrush(wx.Brush((187,173,160)))
 300         dc.SetPen(wx.Pen((187,173,160)))
 301         dc.DrawRoundedRectangle(int(505-15-bstScoreBoardW),40,bstScoreBoardW,50,3)
 302         dc.DrawRoundedRectangle(int(505-15-bstScoreBoardW-5-curScoreBoardW),40,curScoreBoardW,50,3)
 303         dc.SetTextForeground((238,228,218))
 304         dc.DrawText(u"BEST",int(505-15-bstScoreBoardW+(bstScoreBoardW-bestLabelSize[0])/2),48)
 305         dc.DrawText(u"SCORE",int(505-15-bstScoreBoardW-5-curScoreBoardW+(curScoreBoardW-scoreLabelSize[0])/2),48)
 306         dc.SetTextForeground((255,255,255))
 307         dc.DrawText(str(self.bstScore),int(505-15-bstScoreBoardW+(bstScoreBoardW-bstScoreSize[0])/2),68)
 308         dc.DrawText(str(self.curScore),int(505-15-bstScoreBoardW-5-curScoreBoardW+(curScoreBoardW-curScoreSize[0])/2),68)
 309 
 310 
 311     # Put rounded rectangular tiles on screen
 312     def drawTiles(self,dc):
 313         dc.SetFont(self.scFont)
 314         for row in range(4):
 315             for col in range(4):
 316                 value = self.data[row][col]
 317                 color = self.colors[value]
 318                 if value==2 or value==4:
 319                     dc.SetTextForeground((119,110,101))
 320                 else:
 321                     dc.SetTextForeground((255,255,255))
 322                 dc.SetBrush(wx.Brush(color))
 323                 dc.SetPen(wx.Pen(color))
 324                 dc.DrawRoundedRectangle(30+col*115,165+row*115,100,100,2)
 325                 size = dc.GetTextExtent(str(value))
 326                 while size[0]>100-15*2: # Changes font size based on number within tile
 327                     self.scFont = wx.Font(self.scFont.GetPointSize()*4/5,wx.SWISS,wx.NORMAL,wx.BOLD)
 328                     dc.SetFont(self.scFont)
 329                     size = dc.GetTextExtent(str(value))
 330                 if value!=0: dc.DrawText(str(value),int(30+col*115+(100-size[0])/2),int(165+row*115+(100-size[1])/2))
 331 
 332 
 333     # Draws everything to the screen
 334     def drawAll(self):
 335         dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
 336         self.drawBg(dc)
 337         self.drawLogo(dc)
 338         self.drawLabel(dc)
 339         self.drawScore(dc)
 340         self.drawTiles(dc)
 341 
 342 
 343     # Calculates current score and checks if it is the best score and if so updates
 344     def drawChange(self,score):
 345         dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
 346         if score:
 347             self.curScore += score
 348             if int(self.curScore) > int(self.bstScore):
 349                 self.bstScore = self.curScore
 350             self.drawScore(dc)
 351         self.drawTiles(dc)
 352 
 353     # Shows creator info
 354 
 355 #---------------------------------------------------------------------------
 356 
 357 if __name__ == "__main__":
 358     app = wx.App()
 359     Frame(u"2048 v1.0.1 by Guolz")
 360     app.MainLoop()


Download source

source.zip


Additional Information

Link :

https://wiki.python.org/moin/GameProgramming

http://mientki.ruhosting.nl/data_www/pylab_works/pw_bricks_2d_scene.html

- - - - -

https://wiki.wxpython.org/TitleIndex

https://docs.wxpython.org/


Thanks to

Mike Driscoll (tic_tac_toe.py coding), Jan Bodnar (puzzle.py coding), Guolz (2048.py coding), the wxPython community...


About this page

Date(d/m/y) Person (bot) Comments :

19/09/20 - Ecco (Created page for wxPython Phoenix).


Comments

- blah, blah, blah...

How to create a game for wxPython - Part 2 (Phoenix) (last edited 2020-10-25 16:50:48 by Ecco)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.