|
|
|
|
"""
|
|
|
|
|
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
|
|
|
|
|
from multiprocessing import connection
|
|
|
|
|
import pygame as pg
|
|
|
|
|
import sys
|
|
|
|
|
import socket
|
|
|
|
|
import SafariChess_backend as backend
|
|
|
|
|
from SafariChess_Classes import Button, DropDown
|
|
|
|
|
from threading import Thread, Lock
|
|
|
|
|
from itertools import count, cycle
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
#设置棋盘的参数
|
|
|
|
|
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 = 20 #棋盘的左边距
|
|
|
|
|
#网络道具
|
|
|
|
|
client = None
|
|
|
|
|
networkMsg = None
|
|
|
|
|
server = None
|
|
|
|
|
port = None
|
|
|
|
|
addr = None
|
|
|
|
|
connection = None
|
|
|
|
|
#网络版更新需要注意多线程的问题?
|
|
|
|
|
server_died_message = 'fucking server died and quit'
|
|
|
|
|
#尝试写一个函数分配一个新线程供监听
|
|
|
|
|
def startNewThread(target):
|
|
|
|
|
thread = Thread(target=target)
|
|
|
|
|
thread.daemon =True
|
|
|
|
|
thread.start()
|
|
|
|
|
def listenFromServer():
|
|
|
|
|
global networkMsg
|
|
|
|
|
try:
|
|
|
|
|
while True:
|
|
|
|
|
recvMsg = client.recv(1024).decode('utf-8')
|
|
|
|
|
if len(recvMsg) != 0:
|
|
|
|
|
networkMsg = json.loads(recvMsg)
|
|
|
|
|
print('receive thread catch: ',networkMsg)
|
|
|
|
|
except socket.error as e:
|
|
|
|
|
#print('Error encountered in connection. Quit.')
|
|
|
|
|
print(e)
|
|
|
|
|
return False
|
|
|
|
|
def startNetworkServices():
|
|
|
|
|
global client,server,port,addr,connection
|
|
|
|
|
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
|
server = '127.0.0.1'
|
|
|
|
|
port = 50005
|
|
|
|
|
addr = (server,port)
|
|
|
|
|
connection = client.connect(addr)
|
|
|
|
|
startNewThread(target=listenFromServer)
|
|
|
|
|
|
|
|
|
|
#等待敌人移动
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
pg.display.flip()
|
|
|
|
|
|
|
|
|
|
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.bmp"), (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))
|
|
|
|
|
music_settings = pg.transform.scale(pg.image.load("Image/music.bmp"),(100,40))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#按钮设置
|
|
|
|
|
#主菜单包含如下按钮:
|
|
|
|
|
#单机游戏,双人游戏,人机对战,退出游戏
|
|
|
|
|
button_1 = Button(bt1,(300,350))
|
|
|
|
|
button_2 = Button(bt2,(300,400))
|
|
|
|
|
button_3 = Button(bt3,(300,450))
|
|
|
|
|
button_4 = Button(bt4,(300,500))
|
|
|
|
|
music_button = Button(music_settings,(700,0))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#音乐设置
|
|
|
|
|
|
|
|
|
|
file=r'./Image/music1.mp3' #要播放的歌曲本地地址
|
|
|
|
|
pg.mixer.init() #mixer的初始化
|
|
|
|
|
music = pg.mixer.music.load(file) #载入一个音乐文件用于播放
|
|
|
|
|
pg.mixer.music.play(-1) #播放音乐,-1表示循环播放
|
|
|
|
|
|
|
|
|
|
COLOR_INACTIVE = (255, 108, 0)
|
|
|
|
|
COLOR_ACTIVE = (255, 208, 0)
|
|
|
|
|
COLOR_LIST_INACTIVE = (0, 143, 90)
|
|
|
|
|
COLOR_LIST_ACTIVE = (3, 252, 140)
|
|
|
|
|
|
|
|
|
|
# music_ops = DropDown([COLOR_INACTIVE, COLOR_ACTIVE],[COLOR_LIST_INACTIVE, COLOR_LIST_ACTIVE],
|
|
|
|
|
# 600,30, 100, 20,
|
|
|
|
|
# pg.font.SysFont("Courier", 20),
|
|
|
|
|
# "Music",
|
|
|
|
|
# music_lists)
|
|
|
|
|
|
|
|
|
|
mode = -1
|
|
|
|
|
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()
|
|
|
|
|
if music_button.rect.collidepoint(event.pos):
|
|
|
|
|
|
|
|
|
|
if pg.mixer.music.get_volume() == 0:
|
|
|
|
|
pg.mixer.music.set_volume(0.5)
|
|
|
|
|
else:
|
|
|
|
|
pg.mixer.music.set_volume(0)
|
|
|
|
|
|
|
|
|
|
pg.display.flip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
screen.blit(music_button.image, music_button.rect)
|
|
|
|
|
pg.display.flip()
|
|
|
|
|
return mode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#绘制Text在屏幕上
|
|
|
|
|
def showText(screen,fontObj,text,x,y):
|
|
|
|
|
textSurfaceObj = fontObj.render(text, True, pg.Color('red'),pg.Color('white'))# 配置要显示的文字
|
|
|
|
|
textRectObj = textSurfaceObj.get_rect()# 获得要显示的对象的rect
|
|
|
|
|
textRectObj.center = (x, y)# 设置显示对象的坐标
|
|
|
|
|
screen.blit(textSurfaceObj, textRectObj)# 绘制字体
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def drawButton22(screen):
|
|
|
|
|
##一些按钮的实例化
|
|
|
|
|
button_stop = Button(pg.transform.scale(pg.image.load("Image/叫停.bmp"),(100,50)),(400,0))
|
|
|
|
|
screen.blit(button_stop.image, button_stop.rect)
|
|
|
|
|
button_quit = Button(pg.transform.scale(pg.image.load("Image/退出.bmp"),(100,50)),(300,0))
|
|
|
|
|
screen.blit(button_quit.image, button_quit.rect)
|
|
|
|
|
button_fail = Button(pg.transform.scale(pg.image.load("Image/认输.bmp"),(100,50)),(500,0))
|
|
|
|
|
screen.blit(button_fail.image, button_fail.rect)
|
|
|
|
|
button_restart = Button(pg.transform.scale(pg.image.load("Image/restart.bmp"),(100,50)),(100,0))
|
|
|
|
|
screen.blit(button_restart.image, button_restart.rect)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main(mode):
|
|
|
|
|
global networkMsg
|
|
|
|
|
networkMsg = None
|
|
|
|
|
pg.init()
|
|
|
|
|
screen = pg.display.set_mode((BOARD_WIDTH + MOVE_LOG_PANEL_WIDTH, BOARD_HEIGHT))
|
|
|
|
|
pg.display.set_caption("Safari Chess Game")
|
|
|
|
|
clock = pg.time.Clock()
|
|
|
|
|
screen.fill(pg.Color("white"))
|
|
|
|
|
loadImages()
|
|
|
|
|
drawBoard(screen)
|
|
|
|
|
isOnline = bool(mode == 2)
|
|
|
|
|
game_state=backend.GameState()
|
|
|
|
|
#* cancelled args: MySide=True if not isOnline else bool(NewPlayerMessage['side']),game_id=NewPlayerMessage['game_id']
|
|
|
|
|
valid_moves=game_state.getAllMoves()
|
|
|
|
|
running = True
|
|
|
|
|
other_joined = False #network element
|
|
|
|
|
other_stage = False #network element
|
|
|
|
|
game_id = None #network element
|
|
|
|
|
MySide = None #network element
|
|
|
|
|
time_out_side = None #network element
|
|
|
|
|
foul = None #network element
|
|
|
|
|
mademove = False
|
|
|
|
|
game_over = False
|
|
|
|
|
square_selected = () #刚开始没有选择任何一个棋子
|
|
|
|
|
click_queue = [] #点击队列,记录第一次点击和第二次点击位置,方便移动棋子
|
|
|
|
|
##音乐按钮,均有
|
|
|
|
|
button_music = Button(pg.transform.scale(pg.image.load("Image/music.bmp"),(80,40)),(650,0))
|
|
|
|
|
screen.blit(button_music.image, button_music.rect)
|
|
|
|
|
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()
|
|
|
|
|
mademove = False
|
|
|
|
|
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:
|
|
|
|
|
counts=20 #双方倒计时
|
|
|
|
|
startNetworkServices()
|
|
|
|
|
#! start login
|
|
|
|
|
myPlayerData = {
|
|
|
|
|
'type': 0, # game state type ?
|
|
|
|
|
'msg': {
|
|
|
|
|
'name': 'myName'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
login_packet = json.dumps(myPlayerData)
|
|
|
|
|
if (sys.version[:1] == '3'):
|
|
|
|
|
login_packet = login_packet.encode('utf-8')
|
|
|
|
|
lastNetworkMsg = networkMsg
|
|
|
|
|
client.send(login_packet)
|
|
|
|
|
login_font = pg.font.SysFont("comicsansms", 32)
|
|
|
|
|
text_object = login_font.render('waiting 4 connection...', True, pg.Color("grey"))
|
|
|
|
|
login_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)
|
|
|
|
|
while networkMsg == None:
|
|
|
|
|
for event in pg.event.get():
|
|
|
|
|
if event.type == pg.QUIT:
|
|
|
|
|
pg.quit()
|
|
|
|
|
sys.exit()
|
|
|
|
|
screen.blit(text_object,login_text_location)
|
|
|
|
|
clock.tick(20)
|
|
|
|
|
pg.display.update()
|
|
|
|
|
|
|
|
|
|
pg.display.flip()
|
|
|
|
|
#! end login
|
|
|
|
|
# 自定义计时事件-----计时器实现
|
|
|
|
|
COUNTS = pg.USEREVENT +1
|
|
|
|
|
# 每隔1秒发送一次自定义事件
|
|
|
|
|
pg.time.set_timer(COUNTS,1000) #以毫秒为单位
|
|
|
|
|
bigfont = pg.font.SysFont("Consolas", 20)
|
|
|
|
|
minfont = pg.font.SysFont("Courier", 18)
|
|
|
|
|
showText(screen,bigfont,"RemainTime:",680,200) #650,250为时间,650,350为对方轮数
|
|
|
|
|
showText(screen,minfont,"Turn:",650,300)
|
|
|
|
|
clock = pg.time.Clock()
|
|
|
|
|
clock.tick(60)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
drawButton22(screen)
|
|
|
|
|
while running:
|
|
|
|
|
#! 特别注意:红方是0,蓝方是1
|
|
|
|
|
#print('current moving color: ',game_state.color())
|
|
|
|
|
if lastNetworkMsg != networkMsg:#handle
|
|
|
|
|
#! 无法解决的问题:判断延迟导致无法同时接收来自服务器的两条转发消息。
|
|
|
|
|
print('catch new msg: ',networkMsg)
|
|
|
|
|
lastNetworkMsg = networkMsg #networkMsg中保存当前字典
|
|
|
|
|
if 'status' in networkMsg.keys():
|
|
|
|
|
#Login_handler
|
|
|
|
|
if networkMsg['status'] == 1: #Finished Login process
|
|
|
|
|
if other_joined == False:
|
|
|
|
|
other_joined = True
|
|
|
|
|
print('Game start 2 play!')
|
|
|
|
|
game_id = networkMsg['game_id']
|
|
|
|
|
MySide = networkMsg['side']
|
|
|
|
|
other_stage = True if networkMsg['side']==1 else False #一开始如果我是蓝方则other_stage为真
|
|
|
|
|
if(other_stage == True):
|
|
|
|
|
print('waiting for other player to move...')
|
|
|
|
|
|
|
|
|
|
#state_game_handler
|
|
|
|
|
elif networkMsg['status'] == 2 : # Stopping request
|
|
|
|
|
print('other player returned special message: ',networkMsg['request'])
|
|
|
|
|
if networkMsg['request']=='quit':
|
|
|
|
|
other_joined = False
|
|
|
|
|
|
|
|
|
|
elif networkMsg['request'] == 'stop':
|
|
|
|
|
game_state.win_person = 'b' if networkMsg['side'] == 1 else 'r'
|
|
|
|
|
pass
|
|
|
|
|
elif networkMsg['request'] == 'report':
|
|
|
|
|
foul = networkMsg['side']
|
|
|
|
|
|
|
|
|
|
otherQuitJson = {
|
|
|
|
|
'type': 3,
|
|
|
|
|
'side': MySide
|
|
|
|
|
}
|
|
|
|
|
client.send(json.dumps(otherQuitJson).encode('utf-8'))
|
|
|
|
|
game_over = True
|
|
|
|
|
|
|
|
|
|
#timeout handler
|
|
|
|
|
elif networkMsg['status'] == 3 :
|
|
|
|
|
time_out_side = networkMsg['side']
|
|
|
|
|
otherQuitJson = {
|
|
|
|
|
'type': 3,
|
|
|
|
|
'side': MySide
|
|
|
|
|
}
|
|
|
|
|
client.send(json.dumps(otherQuitJson).encode('utf-8'))
|
|
|
|
|
game_over = True
|
|
|
|
|
|
|
|
|
|
#Move handler
|
|
|
|
|
elif 'src' and 'dst' in networkMsg.keys():
|
|
|
|
|
theMove = backend.Move([networkMsg['src']['y'],networkMsg['src']['x']],[networkMsg['dst']['y'],networkMsg['dst']['x']],game_state.board)
|
|
|
|
|
game_state.makeMove(theMove)
|
|
|
|
|
valid_moves = game_state.getAllMoves()
|
|
|
|
|
other_stage = not other_stage
|
|
|
|
|
counts=20
|
|
|
|
|
#轮到的方
|
|
|
|
|
showText(screen,bigfont,backend.GameState().color() ,700,350)
|
|
|
|
|
pg.display.update()
|
|
|
|
|
game_state.conquer()#update conquer stage
|
|
|
|
|
|
|
|
|
|
thisMove = None
|
|
|
|
|
for e in pg.event.get():
|
|
|
|
|
#接下来处理游戏中的事件
|
|
|
|
|
if e.type == pg.QUIT:
|
|
|
|
|
quitJson = {
|
|
|
|
|
"type": 2,
|
|
|
|
|
"msg": {
|
|
|
|
|
"request": "quit",
|
|
|
|
|
"game_id": game_id,
|
|
|
|
|
"side": MySide
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
client.send(json.dumps(quitJson).encode('utf-8'))
|
|
|
|
|
pg.quit()
|
|
|
|
|
sys.exit()
|
|
|
|
|
elif e.type == pg.MOUSEBUTTONDOWN:
|
|
|
|
|
#鼠标点击事件:用于选择棋子,移动棋子
|
|
|
|
|
if not game_over and not other_stage and other_joined:
|
|
|
|
|
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)
|
|
|
|
|
thisMove = move
|
|
|
|
|
if move in valid_moves:
|
|
|
|
|
game_state.makeMove(move)
|
|
|
|
|
mademove = True
|
|
|
|
|
square_selected = ()
|
|
|
|
|
click_queue = []
|
|
|
|
|
else:
|
|
|
|
|
click_queue = [square_selected]
|
|
|
|
|
elif e.type == COUNTS:# 判断事件是否为计时事件
|
|
|
|
|
counts -= 1
|
|
|
|
|
text = str(counts).rjust(3) if counts >= 0 else '0'
|
|
|
|
|
showText(screen,bigfont,text,650,250)
|
|
|
|
|
pg.display.update()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if mademove:
|
|
|
|
|
valid_moves = game_state.getAllMoves()
|
|
|
|
|
mademove = False
|
|
|
|
|
if isOnline:
|
|
|
|
|
print('waiting for the other player to move...')
|
|
|
|
|
|
|
|
|
|
other_stage = not other_stage
|
|
|
|
|
thisMoveJson = {
|
|
|
|
|
'type': 1,
|
|
|
|
|
'msg': {
|
|
|
|
|
"game_id": game_id,
|
|
|
|
|
"side": MySide,
|
|
|
|
|
"chessman": int(thisMove.cur_piece[1:]),
|
|
|
|
|
"src": {
|
|
|
|
|
"y": thisMove.start_row,
|
|
|
|
|
"x": thisMove.start_col
|
|
|
|
|
},
|
|
|
|
|
"dst": {
|
|
|
|
|
"y": thisMove.end_row,
|
|
|
|
|
"x": thisMove.end_col
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
client.send(json.dumps(thisMoveJson).encode('utf-8'))
|
|
|
|
|
|
|
|
|
|
#思路变成:定时对敌方进行扫描,若收到更新相关包则进行局面更新。
|
|
|
|
|
|
|
|
|
|
ShowGameState(screen,game_state,valid_moves,square_selected)
|
|
|
|
|
|
|
|
|
|
if game_state.conquer() and not game_over:
|
|
|
|
|
print("GAME OVER!")
|
|
|
|
|
#
|
|
|
|
|
if game_state.win_person == ('b' if MySide == 1 else 'r'):
|
|
|
|
|
winJson = {
|
|
|
|
|
'type': 2,
|
|
|
|
|
'msg': {
|
|
|
|
|
'request': 'stop',
|
|
|
|
|
'game_id': game_id,
|
|
|
|
|
'side': MySide
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
client.send(json.dumps(winJson).encode("utf-8"))
|
|
|
|
|
print('i won, and game over message sent.')
|
|
|
|
|
game_over = True
|
|
|
|
|
#print('game over label confirmed.')
|
|
|
|
|
|
|
|
|
|
if game_over and other_joined:
|
|
|
|
|
if (game_state.win_person == ''): game_state.conquer()
|
|
|
|
|
showGameOverText(screen,"player "+game_state.win_person+" wins")
|
|
|
|
|
if game_over and not other_joined:
|
|
|
|
|
showGameOverText(screen,"player "+ ("b" if MySide==0 else "r") + " quitted the game") #对手退出了
|
|
|
|
|
if time_out_side != None:
|
|
|
|
|
showGameOverText(screen,"player "+ ("b" if time_out_side==1 else "r")+" timed out") #超时了
|
|
|
|
|
|
|
|
|
|
clock.tick(50)
|
|
|
|
|
pg.display.flip()
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
#print("Loading...")
|
|
|
|
|
#print("Initialing game...")
|
|
|
|
|
mode = MainMenu()
|
|
|
|
|
#mode = 2
|
|
|
|
|
main(mode)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|