main.py
import random
import keyboard as keyboard
from kivy.app import App
from kivy.graphics import BorderImage, Color
from kivy.properties import NumericProperty, ListProperty
from kivy.uix.widget import Widget
from kivy.core.window import Window, Keyboard
from kivy.vector import Vector
from kivy.utils import get_color_from_hex
spacing = 15
colors = ('eee4da', 'ede0c8', 'f2b179', 'f59563', 'f67c5f', 'f65e3b', 'edcf72', 'edcc61', 'ebc850', 'edc53f', 'edc22e')
tile_colors = {2 ** i: color for i, color in enumerate(colors, start=1)}
key_vectors = {
Keyboard.keycodes['up']: (0, 1),
Keyboard.keycodes['right']: (1, 0),
Keyboard.keycodes['down']: (0, -1),
Keyboard.keycodes['left']: (-1, 0),
}
class Tile(Widget):
font_size = NumericProperty(24)
number = NumericProperty(2)
color = ListProperty(get_color_from_hex(tile_colors[2]))
number_color = ListProperty(get_color_from_hex('776e65'))
def __init__(self, number=2, **kwargs):
super(Tile, self).__init__(**kwargs)
self.font_size = 0.5 * self.width
self.number = number
self.update_colors()
def update_colors(self):
self.color = get_color_from_hex(tile_colors[self.number])
if self.number > 4:
self.number_color = get_color_from_hex('f9f6f2')
def resize(self, pos, size):
self.pos = pos
self.size = size
self.font_size = 0.5 * self.width
def all_cells(flip_x=False, flip_y=False):
for x in (reversed(range(4)) if flip_x else range(4)):
for y in (reversed(range(4)) if flip_y else range(4)):
yield (x, y)
class Board(Widget):
b = None
def __init__(self, **kwargs):
super(Board, self).__init__(**kwargs)
self.resize()
def reset(self):
self.b = [[None for i in range(4)] for j in range(4)]
self.new_tile()
self.new_tile()
def new_tile(self, *args):
empty_cells = [(x,y) for x, y in all_cells()
if self.b[x][y] is None]
if not empty_cells:
print('Game over (tentative: no cells)')
return
x, y = random.choice(empty_cells)
tile = Tile(pos=self.cell_pos(x,y),
size=self.cell_size)
self.b[x][y] = tile
self.add_widget(tile)
def move(self, dir_x, dir_y):
dir_x = int(dir_x)
dir_y = int(dir_y)
for board_x, board_y in all_cells(dir_x > 0, dir_y > 0):
tile = self.b[board_x][board_y]
if not tile:
continue
x, y = board_x, board_y
while self.can_move(x + dir_x, y + dir_y):
self.b[x][y] = None
x += dir_x
y += dir_y
self.b[x][y] = tile
if x == board_x and y == board_y:
continue
anim = Animation(pos=self.cell_pos(x, y), duration=0.25, transition='linear')
anim.start(tile)
def cell_pos(self, board_x, board_y):
return (self.x + board_x * (self.cell_size[0] + spacing) + spacing,
self.y + board_y * (self.cell_size[1] + spacing) + spacing)
def valid_cell(self, board_x, board_y):
return (board_x >= 0 and board_y >=0 and board_x <=3 and board_y <=3)
def can_move(self, board_x, board_y):
return (self.valid_cell(board_x, board_y) and self.b[board_x][board_y] is None)
def resize(self, *args):
# 设置尺寸
self.cell_size = (0.25 * (self.width -5 * spacing), ) * 2
# redraw background
self.canvas.before.clear()
with self.canvas.before:
# 设置背景
BorderImage(pos=self.pos, size=self.size, source='board.png')
Color(*get_color_from_hex('ccc0b4'))
for board_x, board_y in all_cells():
BorderImage(pos=self.cell_pos(board_x, board_y),
size=self.cell_size, source='cell.png')
if not self.b:
return
for board_x, board_y in all_cells():
tile = self.b[board_x][board_y]
if tile:
tile.resize(pos=self.cell_pos(board_x, board_y), size=self.cell_size)
on_pos = resize
on_size = resize
class GameApp(App):
def build(self):
# 通过ID获取到FloatLayoit布局中的Board部件
board = self.root.ids.board
board.reset()
if __name__ == '__main__':
Window.clearcolor = get_color_from_hex('faf8ef')
GameApp().run()
game.kv
#:set padding 20
FloatLayout:
Board:
id: board
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
size_hint: (None, None)
center: root.center
size: [min(root.width, root.height) -2 * padding] * 2
<Tile>:
canvas:
Color:
rgb: self.color
BorderImage:
pos: self.pos
size: self.size
source: 'cell.png'
Label:
pos: root.pos
size: root.size
bold: True
color: root.number_color
font_size: root.font_size
text: str(root.number)

x, y board_x board_y
(board_x, board_y)坐标 如(0,0), (0, 1), (1, 1),(2, 2) 等
board_x和board_y则是用来表示游戏界面中方块的索引位置。它们是以0为起始索引的整数值,用于表示方块在游戏棋盘中的位置。
区别在于,x和y是以像素为单位的坐标,用于确定方块在屏幕上的具体位置;而board_x和board_y是以索引为单位的坐标,用于确定方块在游戏棋盘中的位置。
在Kivy 2048项目中,x和y是来表示游戏界面中棋盘的位置坐标。它们分别代表了棋盘在水平和垂直方向上的位置。
本文详细介绍了使用Kivy库在Python中开发的一款2048游戏,涉及Tile类、Board类和GameApp类的实现,展示了如何处理游戏逻辑、方块移动、重绘背景以及UI组件的设计。
2648

被折叠的 条评论
为什么被折叠?



