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是来表示游戏界面中棋盘的位置坐标。它们分别代表了棋盘在水平和垂直方向上的位置。