]>
git.siccegge.de Git - ghextris.git/blob - ghextris.py
5fb037d4fec43fa415587074f0c5ff24a7ae8537
3 # Gnome-hextris; a free rewrite of the xhextris game in Python for Gnome
4 # Copyright 2004 Mikko Rauhala <mjr@iki.fi>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 # This will be overwritten for the installed version:
29 gi
.require_version("Gtk", "3.0")
31 from gi
.repository
import Gtk
35 from gi
.repository
import GObject
46 # self.piecewidth = 20
47 # self.piecenarrow = 20
49 self
.cols
= 13 # Must be odd or weirdness ensues
51 self
.width
= (((self
.cols
/2)+2)*self
.piecewidth
+
52 ((self
.cols
/2)+1) * self
.piecenarrow
) + 2
53 self
.height
= (self
.rows
+1) * self
.pieceheight
+ 2
55 self
.colors
= ("blue", "yellow", "red", "orange", "green", "purple",
56 "cyan", "gray45", "magenta", "lightblue")
57 self
.deltax
= (-1, -1, -1, 0, 0, 0, 0, 0, -1, -1)
58 self
.deltay
= (-1, -1, -1, 0, 0, 0, 0, 0, -1, -1)
60 (((0,), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)),
61 ((0,), (0, 0, 0, 1), (0, 1, 1), (1,)),
62 ((0,), (1, 1), (0, 0, 1, 1)),
63 ((0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)),
64 ((0,), (0, 0, 0, 1, 1), (0, 1, 1)),
65 ((0,), (0, 1), (0, 0, 1, 1), (0, 0, 0, 0, 1))),
66 (((0,), (0, 0, 1), (0, 0, 1, 1), (0, 0, 0, 1)),
67 ((0,), (0, 0, 0, 1), (0, 0, 1), (0, 1, 1)),
68 ((0,), (0,), (1, 1, 1, 1)),
69 ((0, 1), (0, 1), (0, 0, 1), (0, 0, 1)),
70 ((0, 0, 0, 1), (0, 0, 1), (0, 1, 1)),
71 ((0,), (0, 1, 0, 1), (0, 0, 1, 0, 1))),
72 (((0,), (0, 0, 1), (0, 1, 1), (0, 1)),
73 ((0,), (0, 1, 0, 1), (1, 0, 1, 0)),
74 ((0, 1), (0, 0, 1), (0, 0, 1, 1)),
75 ((0, 0, 0, 1), (0, 0, 0, 1), (0, 0, 1), (0, 0, 1)),
76 ((0,), (0,), (0, 1, 1, 1, 1)),
77 ((0,), (0, 1), (0, 0, 1), (0, 0, 1, 1))),
78 (((0, 1, 0), (0, 1, 0), (1, 0, 1)),
79 ((0,), (1, 1, 1), (0, 1, 0))),
80 (((0, 1), (1,), (1, 1)),
81 ((0, 1), (1, 0, 1), (1,)),
82 ((0, 1), (1, 0, 1), (0, 0, 1)),
83 ((0, 1), (0, 0, 1), (0, 1, 1)),
84 ((0,), (0, 0, 1), (1, 1, 1)),
85 ((0,), (1,), (1, 1, 1))),
86 (((0,), (0, 1), (1, 1, 1)),
87 ((0,), (1, 1), (1, 1, 0)),
88 ((0, 1), (1, 1), (1,)),
90 ((0, 1), (0, 1, 1), (0, 0, 1)),
91 ((0,), (0, 1, 1), (0, 1, 1))),
92 (((0, 1), (0, 1), (0, 1, 1)),
93 ((0,), (0, 1, 1), (1, 1)),
94 ((0,), (1, 1), (1, 0, 1)),
95 ((0, 1), (1, 1), (0, 1)),
96 ((0, 1), (0, 1, 1), (1,)),
97 ((0,), (1, 1, 1), (0, 0, 1))),
98 (((0, 1), (0, 1), (1, 1)),
99 ((0,), (1, 1, 1), (1,)),
100 ((0, 1), (1, 1), (0, 0, 1)),
101 ((0, 1), (0, 1, 1), (0, 1)),
102 ((0,), (0, 1, 1), (1, 0, 1)),
103 ((0,), (1, 1), (0, 1, 1))),
104 (((0,), (0, 0, 1), (0, 0, 1), (0, 0, 1, 1)),
105 ((0,), (0, 0, 0, 1), (0, 1, 1), (0, 1)),
106 ((0,), (0, 1), (1, 0, 1, 1)),
107 ((0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)),
108 ((0, 0, 0, 1), (0, 0, 0, 1), (0, 1, 1)),
109 ((0,), (0, 1), (0, 0, 1, 1, 1))),
110 (((0,), (0, 0, 1), (0, 0, 1), (0, 1, 1)),
111 ((0,), (0, 0, 0, 1), (1, 1, 1)),
112 ((0, 1), (0, 1), (0, 0, 1, 1)),
113 ((0, 0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)),
114 ((0,), (0, 0, 0, 1), (0, 1, 1, 0, 1)),
115 ((0,), (0, 1), (0, 0, 1, 1), (0, 0, 0, 1)))
119 self
.speed_orig
= 400
121 self
.speed_ratio
= 0.99
122 self
.speed_reset
= False
131 self
.nextpiece
= False
135 def draw_hexagon(self
, group
, color
):
137 pts
.append ((self
.piecewidth
- self
.piecenarrow
)/2)
139 pts
.append (self
.piecewidth
- pts
[0])
141 pts
.append (self
.piecewidth
)
142 pts
.append (self
.pieceheight
/2)
144 pts
.append (self
.pieceheight
)
151 item
= group
.add ("GnomeCanvasPolygon", points
= pts
, fill_color
= color
,
152 outline_color
= "black", width_units
= 1)
155 def draw_piece(self
, group
, matrix
, color
):
156 for i
in range(len(matrix
)):
157 for j
in range(len(matrix
[i
])):
158 if matrix
[i
][j
] != 0:
159 g
= group
.add("GnomeCanvasGroup",
160 x
= (j
*(self
.piecewidth
+self
.piecenarrow
)/2),
161 y
= ((i
* (self
.pieceheight
)) +
162 ((j
%2) * self
.pieceheight
/2)))
163 self
.draw_hexagon(g
, color
)
165 def place_piece(self
, group
, matrix
, color
, x
, y
):
166 piecegroup
= group
.add("GnomeCanvasGroup",
167 x
= (x
+1)*((self
.piecewidth
+self
.piecenarrow
)/2),
168 y
= ((y
* self
.pieceheight
) -
169 (((x
%2)+1) * self
.pieceheight
/2)))
170 self
.draw_piece(piecegroup
, matrix
, color
)
173 def init_board(self
):
174 board
= self
.canvas
.root()
175 for i
in range(self
.rows
+1):
177 boardhex
= board
.add("GnomeCanvasGroup",
178 x
= j
* (self
.piecewidth
*(self
.cols
/2+1) +
179 self
.piecenarrow
*(self
.cols
/2+1)),
180 y
= i
* self
.pieceheight
)
181 self
.draw_hexagon(boardhex
, "gray")
182 for i
in range(self
.cols
/2):
183 boardhex
= board
.add("GnomeCanvasGroup",
184 x
= (i
+1) * (self
.piecewidth
+
186 y
= self
.rows
* self
.pieceheight
)
187 self
.draw_hexagon(boardhex
, "gray")
188 for i
in range(self
.cols
/2+1):
189 boardhex
= board
.add("GnomeCanvasGroup",
190 x
= (i
* (self
.piecewidth
+ self
.piecenarrow
)+
191 (self
.piecewidth
+ self
.piecenarrow
)/2),
192 y
= ((self
.rows
*2-1) * self
.pieceheight
)/2)
193 self
.draw_hexagon(boardhex
, "gray")
195 def on_new_activate(self
, event
):
196 self
.speed
= self
.speed_orig
204 if self
.board
!= False:
206 self
.board
= self
.canvas
.root().add("GnomeCanvasGroup", x
= 0, y
= 0)
209 for i
in range(self
.rows
):
210 self
.field
.append([])
211 for j
in range(self
.cols
):
212 self
.field
[i
].append(0)
215 for i
in range(self
.rows
):
216 self
.rowgroups
.append(self
.board
.add("GnomeCanvasGroup", x
= 0,
217 y
= i
* self
.pieceheight
))
219 self
.nextnum
= random
.randint(0, 9)
222 if self
.running
== False:
223 GObject
.timeout_add(self
.speed
, self
.timer_handler
)
226 self
.speed_reset
= True
230 def on_about_activate(self
, event
):
231 aTree
= self
.builder
.get_object("about")
232 about
= aTree
.get_widget("about")
233 about
.set_property("name", "Ghextris")
234 about
.set_property("version", VERSION
)
237 def on_pause_game_activate(self
, event
):
238 if self
.lost
== True:
240 if self
.paused
== True:
246 def on_quit_activate(self
, event
):
250 gnome
.init("Ghextris", VERSION
)
251 gettext
.install("ghextris")
252 self
.builder
= Gtk
.Builder()
253 self
.builder
.add_from_file(os
.path
.join(SHAREDIR
, "ghextris.builder"))
254 wTree
=self
.builder
.get_object("GhextrisApp")
255 dic
= {"on_new_activate": self
.on_new_activate
,
256 "on_pause_game_activate": self
.on_pause_game_activate
,
257 "on_quit_activate": self
.on_quit_activate
,
258 "on_about_activate": self
.on_about_activate
}
259 wTree
.signal_autoconnect(dic
)
261 win
= wTree
.get_widget("GhextrisApp")
262 self
.canvas
= wTree
.get_widget("canvas")
263 preview
= wTree
.get_widget("previewcanvas")
264 appbar
= wTree
.get_widget("appbar").get_children()[0]
265 self
.appbar
= appbar
.get_children()[0]
267 win
.connect('destroy', self
.on_quit_activate
)
269 self
.canvas
.set_size_request(self
.width
, self
.height
)
270 self
.canvas
.set_scroll_region(0, 0, self
.width
, self
.height
)
273 preview
.set_size_request(self
.piecewidth
* 4, self
.pieceheight
* 5)
275 self
.preview
= preview
.root()
277 win
.connect("key-press-event", self
.key_handler
)
286 def next_piece(self
):
287 self
.piecenum
= self
.nextnum
288 self
.nextnum
= random
.randint(0, 9)
290 self
.piece_x
= (self
.cols
/2)-1 + self
.deltax
[self
.piecenum
]
291 self
.piece_y
= -3 + self
.deltax
[self
.piecenum
]
292 self
.piece
= self
.place_piece(self
.board
, self
.pieces
[self
.piecenum
][0],
293 self
.colors
[self
.piecenum
%(len(self
.colors
)+1)],
294 self
.piece_x
, self
.piece_y
)
296 if self
.nextpiece
!= False:
297 self
.nextpiece
.destroy()
298 self
.nextpiece
= self
.place_piece(self
.preview
,
299 self
.pieces
[self
.nextnum
][0],
300 self
.colors
[self
.nextnum
%(len(self
.colors
)+1)],
301 self
.deltax
[self
.nextnum
],
302 self
.deltay
[self
.nextnum
])
304 def timer_handler(self
):
305 if self
.lost
== True:
309 if self
.paused
== True:
313 if self
.check_collisions() == True:
316 if self
.top_occupied() != True:
320 if self
.hiscore
< self
.score
:
321 self
.hiscore
= self
.score
326 self
.piece
.move(0, self
.pieceheight
)
328 if self
.speed_reset
== True:
329 self
.speed_reset
= False
330 GObject
.timeout_add(int(self
.speed
), self
.timer_handler
)
335 def update_appbar(self
):
336 self
.appbar
.set_text("%s: %d | %s: %d" % (_("Score"), self
.score
,
340 def key_handler(self
, widget
, event
=None):
341 if self
.lost
== True:
344 if event
.keyval
== Gdk
.KEY_p
and self
.lost
== False:
345 if self
.paused
== True:
351 if self
.paused
== True:
354 if event
.keyval
== Gdk
.KEY_Up
or event
.keyval
== Gdk
.KEY_Down
:
355 if event
.keyval
== Gdk
.KEY_Up
:
359 old_attitude
= self
.attitude
360 self
.attitude
= ((self
.attitude
+ attitude_change
+
361 len(self
.pieces
[self
.piecenum
])) %
362 len(self
.pieces
[self
.piecenum
]))
363 if self
.check_collisions() == True:
364 self
.attitude
= old_attitude
368 self
.piece
= self
.place_piece(self
.board
,
369 self
.pieces
[self
.piecenum
][self
.attitude
],
370 self
.colors
[self
.piecenum
%(len(self
.colors
)+1)],
371 self
.piece_x
, self
.piece_y
);
374 if event
.keyval
== Gdk
.KEY_Left
or event
.keyval
== Gdk
.KEY_Right
:
375 if event
.keyval
== Gdk
.KEY_Left
:
379 self
.piece_x
+= deltax
382 if self
.piece_x
%2 == 0:
383 deltay
+= self
.pieceheight
/2
385 deltay
-= self
.pieceheight
/2
387 if self
.check_collisions() == True:
389 self
.piece_x
-= deltax
392 deltay
+= self
.pieceheight
393 if self
.check_collisions() == True:
394 self
.piece_x
-= deltax
398 self
.piece
.move(deltax
*(self
.piecewidth
+self
.piecenarrow
)/2, deltay
)
401 if event
.keyval
== Gdk
.KEY_space
:
402 orig_piece_y
= self
.piece_y
403 while self
.check_collisions() == False:
406 self
.piece
.move(0, self
.pieceheight
*(self
.piece_y
- orig_piece_y
))
407 self
.score
+= self
.piece_y
- orig_piece_y
408 if self
.score
> self
.hiscore
:
409 self
.hiscore
= self
.score
411 if self
.top_occupied() != True:
415 if self
.hiscore
< self
.score
:
416 self
.hiscore
= self
.score
423 def check_collisions(self
):
424 for i
in range(len(self
.pieces
[self
.piecenum
][self
.attitude
])):
425 for j
in range(len(self
.pieces
[self
.piecenum
][self
.attitude
][i
])):
426 if self
.pieces
[self
.piecenum
][self
.attitude
][i
][j
] != 0:
427 if j
%2 == 0 and self
.piece_x
%2 == 1:
431 if j
+ self
.piece_x
< 0 or j
+ self
.piece_x
>= self
.cols
:
433 if ((i
+ self
.piece_y
+ deltay
> 0) and
434 (i
+ self
.piece_y
+ deltay
>= self
.rows
or
435 self
.field
[i
+ self
.piece_y
+ deltay
][j
+ self
.piece_x
] != 0)):
439 def update_field(self
):
440 for i
in range(len(self
.pieces
[self
.piecenum
][self
.attitude
])):
441 for j
in range(len(self
.pieces
[self
.piecenum
][self
.attitude
][i
])):
442 if self
.pieces
[self
.piecenum
][self
.attitude
][i
][j
] != 0:
443 if j
%2 == 0 and self
.piece_x
%2 == 1:
447 if i
+self
.piece_y
+deltay
>= 0:
448 self
.field
[i
+ self
.piece_y
+ deltay
][j
+ self
.piece_x
] = 1
449 self
.place_piece(self
.rowgroups
[i
+self
.piece_y
+deltay
],
451 self
.colors
[self
.piecenum
%(len(self
.colors
)+1)],
452 j
+ self
.piece_x
- 1, 0)
456 def collapse_rows(self
):
458 for i
in range(self
.rows
):
460 for j
in range(self
.cols
):
461 if self
.field
[i
][j
] == 0:
467 self
.speed
*= self
.speed_ratio
468 self
.speed_reset
= True
469 self
.rowgroups
[i
].destroy()
470 for j
in range(i
-1, -1, -1):
471 self
.rowgroups
[j
].move(0, self
.pieceheight
)
472 self
.rowgroups
[j
+1] = self
.rowgroups
[j
]
473 self
.field
[j
+1] = self
.field
[j
]
475 for j
in range(self
.cols
):
476 self
.field
[0].append(0)
477 self
.rowgroups
[0] = self
.board
.add("GnomeCanvasGroup", x
= 0,
480 self
.score
+= row_points
481 if self
.score
> self
.hiscore
:
482 self
.hiscore
= self
.score
485 def top_occupied(self
):
486 for i
in range(self
.cols
):
487 if self
.field
[0][i
] != 0:
491 if __name__
== '__main__':