例子
代码:
#!/usr/bin/env python3
# Created by xiaosanyu at 16/7/6
# section 152
TITLE = "Snake game"
DESCRIPTION = """
Snake is an older classic video game. It was first created in late 70s.
Later it was brought to PCs. In this game the player controls a snake.
The objective is to eat as many apples as possible.
Each time the snake eats an apple, its body grows.
The snake must avoid the walls and its own body.
This game is sometimes called Nibbles.
"""
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib
import cairo
import sys
import random
import os
FONT_SIZE = 14
WIDTH = 300
HEIGHT = 270
DOT_SIZE = 10
ALL_DOTS = int(WIDTH * HEIGHT / (DOT_SIZE * DOT_SIZE))
RAND_POS = 26
DELAY = 200
x = [0] * ALL_DOTS
y = [0] * ALL_DOTS
class Board(Gtk.DrawingArea):
def __init__(self):
super(Board, self).__init__()
self.modify_bg(Gtk.StateFlags.NORMAL, Gdk.Color(0, 0, 0))
self.set_size_request(WIDTH, HEIGHT)
self.connect("draw", self.draw)
self.init_game()
def on_timer(self):
if self.inGame:
self.check_apple()
self.check_collision()
self.move()
self.queue_draw()
return True
else:
return False
def init_game(self):
self.left = False
self.right = True
self.up = False
self.down = False
self.inGame = True
self.dots = 3
for i in range(self.dots):
x[i] = 50 - i * 10
y[i] = 50
try:
self.dot = cairo.ImageSurface.create_from_png(os.path.join(os.path.dirname(__file__), "../data/dot.png"))
self.head = cairo.ImageSurface.create_from_png(os.path.join(os.path.dirname(__file__), "../data/head.png"))
self.apple = cairo.ImageSurface.create_from_png(
os.path.join(os.path.dirname(__file__), "../data/apple.png"))
except Exception as e:
print(e)
sys.exit(1)
self.locate_apple()
self.start_game()
def start_game(self):
GLib.timeout_add(DELAY, self.on_timer)
def draw(self, widget, cr):
if self.inGame:
cr.set_source_rgb(0.6, 0.6, 0.6)
cr.paint()
cr.set_source_surface(self.apple, self.apple_x, self.apple_y)
cr.paint()
for z in range(self.dots):
if z == 0:
cr.set_source_surface(self.head, x[z], y[z])
cr.paint()
else:
cr.set_source_surface(self.dot, x[z], y[z])
cr.paint()
else:
self.game_over(widget, cr)
def game_over(self, widget, cr):
w = widget.get_allocated_width()
h = widget.get_allocated_height()
(x, y, width, height, dx, dy) = cr.text_extents("Game Over")
cr.set_source_rgb(65535, 0, 0)
cr.set_font_size(FONT_SIZE)
cr.move_to((w - width) / 2, h / 2)
cr.show_text("Game Over")
self.inGame = False
def check_apple(self):
if x[0] == self.apple_x and y[0] == self.apple_y:
self.dots += 1
self.locate_apple()
def move(self):
z = self.dots
while z > 0:
x[z] = x[(z - 1)]
y[z] = y[(z - 1)]
z -= 1
if self.left:
x[0] -= DOT_SIZE
if self.right:
x[0] += DOT_SIZE
if self.up:
y[0] -= DOT_SIZE
if self.down:
y[0] += DOT_SIZE
def check_collision(self):
z = self.dots
while z > 0:
if z > 4 and x[0] == x[z] and y[0] == y[z]:
self.inGame = False
z -= 1
if y[0] > HEIGHT - DOT_SIZE:
self.inGame = False
if y[0] < 0:
self.inGame = False
if x[0] > WIDTH - DOT_SIZE:
self.inGame = False
if x[0] < 0:
self.inGame = False
def locate_apple(self):
r = random.randint(0, RAND_POS)
self.apple_x = r * DOT_SIZE
r = random.randint(0, RAND_POS)
self.apple_y = r * DOT_SIZE
def on_key_down(self, event):
key = event.keyval
if key == Gdk.KEY_Left and not self.right:
self.left = True
self.up = False
self.down = False
if key == Gdk.KEY_Right and not self.left:
self.right = True
self.up = False
self.down = False
if key == Gdk.KEY_Up and not self.down:
self.up = True
self.right = False
self.left = False
if key == Gdk.KEY_Down and not self.up:
self.down = True
self.right = False
self.left = False
if key == Gdk.KEY_space:
if self.inGame:
self.inGame = False
else:
self.inGame = True
self.start_game()
class Snake(Gtk.Window):
def __init__(self):
super(Snake, self).__init__()
self.set_title('Snake')
self.set_size_request(WIDTH, HEIGHT)
self.set_resizable(False)
self.move((Gdk.Screen.width() - WIDTH) / 2, (Gdk.Screen.height() - HEIGHT) / 2)
self.board = Board()
self.connect("key-press-event", self.on_key_down)
self.add(self.board)
self.connect("destroy", Gtk.main_quit)
self.show_all()
def on_key_down(self, widget, event):
key = event.keyval
self.board.on_key_down(event)
def main():
Snake()
Gtk.main()
if __name__ == "__main__":
main()