""" Course: Programming practice Students: Qu Qian /Tan Zhengyuan """ """ Safafi Chess Game/SFF Chess Game (Animal Chess Game) Main code for run the game it handle user input and GUI """ import colorsys import json import pygame as pg import sys import socket import SafariChess_backend as backend from SafariChess_Classes import Button from threading import Thread, Lock #设置棋盘的参数 WIDTH = 1000 HEIGHT = 800 BOARD_WIDTH = 800 BOARD_HEIGHT = 600 SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 MOVE_LOG_PANEL_WIDTH = 0 MOVE_LOG_PANEL_HEIGHT = BOARD_HEIGHT DIMENSION = 8 DIMENSION_ROWS = 7 DIMENSION_COLUMNS = 9 SIZE = 64 IMAGES = {} bias_top = 100 #棋盘的上边距 bias_left = 100 #棋盘的左边距 #multithreading? mutex = Lock() mutex_playing = Lock() def loadImages():#加载图片,a,b双方分别有象狮豹狼狐鹰鼠七个角色 pieces = ["r7", "r6", "r5", "r4", "r3", "r2", "r1", "b7", "b6", "b5", "b4", "b3", "b2", "b1", ] for piece in pieces:#字典的形式存储图片 IMAGES[piece] = pg.transform.scale(pg.image.load("./Image/pieces/pieces_rb/" + piece + ".png"), (SIZE - 10, SIZE - 10)) tools = ["trap", "home1","home2"] for tool in tools: IMAGES[tool] = pg.transform.scale(pg.image.load("./Image/tools/" + tool + ".jpg"), (SIZE-10, SIZE-10)) #screen = pg.display.set_mode((BOARD_WIDTH + MOVE_LOG_PANEL_WIDTH, BOARD_HEIGHT))#设置窗口大小 #screen.fill(pg.Color("white")) def drawBoard(screen):#绘制棋盘:格子,河流,陷阱,巢穴 #colors = [(255, 255, 255), (0, 0, 0)] for row in range(DIMENSION_ROWS): for column in range(DIMENSION_COLUMNS): pg.draw.rect(screen, pg.Color(199,237,204), pg.Rect(bias_left+column * SIZE, bias_top+row * SIZE, SIZE, SIZE)) pg.draw.rect(screen, pg.Color(90,150,75), pg.Rect((column * SIZE) + bias_left+3, (row * SIZE) + 3+bias_top, SIZE - 4, SIZE - 4)) #画河流 for row in [1,2,4,5]: for column in [3,4,5]: pg.draw.rect(screen, pg.Color(67,142,219),pg.Rect((column * SIZE) +bias_left+2, (row * SIZE) +bias_top +3, SIZE-2,SIZE-2)) #画陷阱 for row in [2,4]: for column in [0,8]: screen.blit(IMAGES["trap"], pg.Rect((column * SIZE) +bias_left+6, (row * SIZE) +bias_top +6, SIZE ,SIZE )) for column in [1,7]: screen.blit(IMAGES["trap"], pg.Rect((column * SIZE) +bias_left+6, (3 * SIZE) +bias_top +6, SIZE ,SIZE )) #画巢穴 screen.blit(IMAGES["home1"], pg.Rect((bias_left+6, (3 * SIZE) +bias_top +6, SIZE ,SIZE ))) screen.blit(IMAGES["home2"], pg.Rect( 8*SIZE+bias_left+6, (3 * SIZE) +bias_top +6, SIZE ,SIZE )) def drawPieces(screen,board): #画棋子的位置 for row in range(DIMENSION_ROWS): for column in range(DIMENSION_COLUMNS): piece = board[row][column] if piece != "00": screen.blit(IMAGES[piece], pg.Rect((column * SIZE) + bias_left + 5, (row * SIZE) + bias_top + 5, SIZE - 10, SIZE - 10)) # square_selected 是当前选中的可以移动的棋子的位置 def protrudeSquares(screen,game_state,square_selected,valid_moves): #高亮选中的棋子接下来可行的位置 if square_selected != (): row = square_selected[0] column = square_selected[1] if game_state.board[row][column][0] == ('r' if game_state.red_to_move else 'b'): # highlight selected square s = pg.Surface((SIZE, SIZE)) s.set_alpha(100) s.fill(pg.Color('blue')) screen.blit(s, (column *SIZE + bias_left, row * SIZE + bias_top)) # highlight moves from that square s.fill(pg.Color('yellow')) for move in valid_moves: if move.start_row == row and move.start_col == column: screen.blit(s, (move.end_col * SIZE + bias_left, move.end_row * SIZE + bias_top)) def ShowGameState(screen,game_state,valid_moves,square_selected):#游戏状态 drawBoard(screen) protrudeSquares(screen,game_state,square_selected,valid_moves) drawPieces(screen,game_state.board) #待开发 def drawMovelog(screen):#绘制移动日志 pass def startGamePage(mode = 1):#开始游戏界面,Human/AI startpage = (''' WELCOME TO ____ ____________ _____ _ / __/ ___/ __ | / __ \ | |__| |___| |__| | | / / |___ ___ ___ ___ \__ | ___| _ / | | | _ \/ _ \/ __/ __| __| | | | | \ \ | \__/\ | | | __/\__ \__ | |____/_| |_| \__| \_____/_| |_|\___||___/___/ ################################################################ Please type one of the numbers below to choose a playing mode: ( 1 ) - 单机游戏 ( 2 ) - 网络对战 ( 3 ) - 人机对战 ( 4 ) - 退出游戏 ################################################################ Current Mode is: %s '''%['单机游戏','网络对战','人机对战','退出游戏'][mode-1]) print(startpage) # 选择游戏模式 not_selected = True p1 , p2 = 0, 0 while not_selected: try: #mode = int(input()) #mode = 1 if mode in [1,2,3,4]: if mode == 1: p1 = 1 p2 = 1 ##其余版本还未写 not_selected = False else: print("Please type one of the numbers below to choose a playing mode:") print(" ( 1 ) - 单机游戏") print(" ( 2 ) - 网络对战") print(" ( 3 ) - 人机对战") print(" ( 4 ) - 退出游戏") except ValueError: print("Wrong Input") return p1, p2, mode def showGameOverText(screen, text): #游戏结束,出现的文字 text是字符串“Left Win”或“Right Win” font = pg.font.SysFont("comicsansms", 32) text_object = font.render(text, True, pg.Color("grey")) text_location = pg.Rect(0, 0, BOARD_WIDTH, BOARD_HEIGHT).move(BOARD_WIDTH / 2 - text_object.get_width() / 2, BOARD_HEIGHT / 2 - text_object.get_height() / 2) screen.blit(text_object, text_location) text_object = font.render(text, False, pg.Color('red')) screen.blit(text_object, text_location.move(-2 , -2)) def MainMenu(): #显示主菜单 pg.init() mainClock = pg.time.Clock() #ui screen = pg.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pg.display.set_caption("SafariChess by ZY&&DQ") bg = pg.transform.scale(pg.image.load("Image/MenuBg.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT)) bt1 = pg.transform.scale(pg.image.load("Image/button1.jpg"),(150,40)) bt2 = pg.transform.scale(pg.image.load("Image/button2.jpg"),(150,40)) bt3 = pg.transform.scale(pg.image.load("Image/button3.jpg"),(150,40)) bt4 = pg.transform.scale(pg.image.load("Image/button4.jpg"),(150,40)) #按钮设置 #主菜单包含如下按钮: #单机游戏,双人游戏,人机对战,退出游戏 button_1 = Button(bt1,(350,350)) button_2 = Button(bt2,(350,400)) button_3 = Button(bt3,(350,450)) button_4 = Button(bt4,(350,500)) mode = -1 p1,p2 = 0,0 run = True while run: mainClock.tick(60) mode = 0 events = pg.event.get() for event in events: if event.type == pg.QUIT: pg.quit() sys.exit() if event.type == pg.KEYDOWN: if event.key == pg.K_ESCAPE: pg.quit() sys.exit() if event.type == pg.MOUSEBUTTONDOWN: if event.button == 1: #左键 if button_1.rect.collidepoint(event.pos): mode = 1 run = False if button_2.rect.collidepoint(event.pos): mode = 2 run = False if button_3.rect.collidepoint(event.pos): mode = 3 run = False if button_4.rect.collidepoint(event.pos): pg.quit() sys.exit() screen.blit(bg, (0, 0)) screen.blit(button_1.image, button_1.rect) screen.blit(button_2.image, button_2.rect) screen.blit(button_3.image, button_3.rect) screen.blit(button_4.image, button_4.rect) pg.display.flip() return mode def main(mode,p1,p2,network = None): NewPlayerMessage = '' #来自对手的信息 if mode == 2: network=backend.Network() player1 = input("Enter your name: ") myPlayerData = { 'type': 0, # game state type ? 'msg': { 'name': player1 } } network.send(myPlayerData) print("Waiting for other player...") NewPlayerMessage = network.receive() print() player2 = NewPlayerMessage['counterpart_name'] pg.init() screen = pg.display.set_mode((BOARD_WIDTH + MOVE_LOG_PANEL_WIDTH, BOARD_HEIGHT)) pg.display.set_caption("Safafi Chess Game") clock = pg.time.Clock() screen.fill(pg.Color("white")) loadImages() drawBoard(screen) isOnline = bool(network != None) game_state=backend.GameState(isNet=isOnline,MySide=True if not isOnline else bool(NewPlayerMessage['side']),game_id=NewPlayerMessage['game_id'],client=network) valid_moves=game_state.getAllMoves() running = True mademove = False game_over = False square_selected = ()#刚开始没有选择任何一个棋子 click_queue = []#点击队列,记录第一次点击和第二次点击位置,方便移动棋子 pg.display.update() startGamePage(mode) if mode == 1: while running: for e in pg.event.get(): #接下来处理游戏中的事件 if e.type == pg.QUIT: pg.quit() sys.exit() elif e.type == pg.MOUSEBUTTONDOWN: #鼠标点击事件:用于选择棋子,移动棋子 if not game_over: mouse_loc = pg.mouse.get_pos() row = int((mouse_loc[1] - bias_top) / SIZE) col = int((mouse_loc[0] - bias_left) / SIZE) #* get position of mouse click if square_selected == (row,col) or col >=DIMENSION_COLUMNS or row >= DIMENSION_ROWS: square_selected = () click_queue = [] else: square_selected = (row,col) click_queue.append(square_selected) if(len(click_queue) == 2): cur_piece_loc = click_queue[0] nxt_piece_loc = click_queue[1] move = backend.Move(cur_piece_loc,nxt_piece_loc,game_state.board) if move in valid_moves: game_state.makeMove(move) mademove = True square_selected = () click_queue = [] else: click_queue = [square_selected] elif e.type == pg.KEYDOWN: #设置某些按键用于悔棋,重新开始游戏,机器提示,退出游戏等功能 pass if mademove: valid_moves = game_state.getAllMoves() ShowGameState(screen,game_state,valid_moves,square_selected) if game_state.conquer(): showGameOverText(screen,"player "+game_state.win_person+" wins") game_over = True clock.tick(60) pg.display.flip() elif mode == 2: while running: for e in pg.event.get(): #接下来处理游戏中的事件 if e.type == pg.QUIT: pg.quit() sys.exit() elif e.type == pg.MOUSEBUTTONDOWN: #鼠标点击事件:用于选择棋子,移动棋子 if not game_over: mouse_loc = pg.mouse.get_pos() row = int((mouse_loc[1] - bias_top) / SIZE) col = int((mouse_loc[0] - bias_left) / SIZE) #* get position of mouse click if square_selected == (row,col) or col >=DIMENSION_COLUMNS or row >= DIMENSION_ROWS: square_selected = () click_queue = [] else: square_selected = (row,col) click_queue.append(square_selected) if(len(click_queue) == 2): cur_piece_loc = click_queue[0] nxt_piece_loc = click_queue[1] move = backend.Move(cur_piece_loc,nxt_piece_loc,game_state.board) if move in valid_moves: game_state.makeMove(move) mademove = True square_selected = () click_queue = [] else: click_queue = [square_selected] elif e.type == pg.KEYDOWN: #设置某些按键用于悔棋,重新开始游戏,机器提示,退出游戏等功能 pass if mademove: valid_moves = game_state.getAllMoves() ShowGameState(screen,game_state,valid_moves,square_selected) #* 网络对战局面更新 if network is not None: print('waiting for other players to move...') otherMove = game_state.dnldmv_server() if game_state.conquer(): showGameOverText(screen,"player "+game_state.win_person+" wins") game_over = True clock.tick(60) pg.display.flip() if __name__ == '__main__': print("Loading...") print("Initialing game...") mode = MainMenu() player1='player1' network = None #前后端通信接口 player2='player2' main(mode,player1,player2,network)