How to create a game for wxPython - Part 2 (Phoenix)
Keywords : Tic tac toe, Puzzle, 2048, Game, Pygame.
Contents
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
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
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
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
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
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...