DDR爱好者之家 Design By 杰米
运行效果
实现代码
# -*- coding: utf-8 -*- import tkinter as tkinter import tkinter.messagebox as mb import random,time class Ball(): ''' 创建Ball类,初始化对象,即创建对象设置属性, init函数是在对象被创建的同时就设置属性的一种方法,Python会在创建新对象时自动调用这个函数。 ''' def __init__(self,canvas,paddle,score,color,init_x=100,init_y=100): ''' Ball类初始化属性 :param canvas:画布 :param paddle:球拍 :param score:得分 :param color:小球的颜色 :param init_x:小球球的初始横坐标,有默认值,可不传 :param init_y:小球球的初始纵坐标,有默认值,可不传 ''' self.canvas = canvas self.paddle = paddle self.score = score self.color = color # 保存tkinter画小球返回的id,为后期移动屏幕上的小球做准备, # 参数分别表示为:(10,10)表示左上角x,y坐标,(30,30)表示右下角x,y坐标,即创建一个直径为20的圆 # fill为小球的填充色 self.id = canvas.create_oval(10,10,30,30,fill=self.color) # 将小球移动到初始位置,初始位置可通过传参进行更改,有默认值 self.canvas.move(self.id,init_x,init_y) # 给一串x分量的起始值(x和y代表横坐标和纵坐标的分量) starts = [-3,-2,-1,1,2,3] # shuffle() 方法将序列的所有元素随机排序 random.shuffle(starts) # 随机混排序,赋值给对象变量x,让它起始的时候获得随机分量值,引起球每次起始角度都不同 self.x = starts[0] # 对象变量y就是垂直分量移动的初始值,等价于上下移动,值代表移动多少像素点 self.y = -3 # winfo_height()函数来获取画布当前的高度,赋值给对象变量 self.canvas_height = self.canvas.winfo_height() # winfo_width()函数来获取画布当前的宽度,赋值给对象变量 self.canvas_width = self.canvas.winfo_width() # 小球是否碰触到画布底部,初始值为False,即没有碰到 self.hit_bottom = False def draw(self): ''' 该函数用于让小球水平和垂直运动,在运动的过程中,判断是否得分、游戏是否结束 ''' # 让小球可以水平和垂直运动 self.canvas.move(self.id,self.x,self.y) # coords函数通过id返回画布球的坐标列表(两个坐标,左上角的坐标和右下角的两个坐标) position = self.canvas.coords(self.id) # 判断小球是否撞到画布顶部或者底部,保证小球反弹回去,不消失 if position[1] <= 0: # 如果小球的左上角y坐标小于0,则向下移动3个像素 self.y = 3 if position[3] >= self.canvas_height: # 如果小球的右下角y坐标大于画布宽度,则表示小球碰到了画布底部,游戏结束 self.hit_bottom = True if self.hit_paddle(position) == True: # 判断 球 是否碰到了 球拍,如果碰到了则使小球回弹 self.y = -3 if position[0] <= 0: # 如果小球的左上角x坐标 小于等于0,则向右移动3个像素 self.x = 3 if position[2] >= self.canvas_width: # 如果小球的右下角x坐标 大于等于画布宽度,则向左移动3个像素 self.x = -3 def hit_paddle(self,position): ''' 该函数用于判断 球 是否碰到了 球拍,如果碰到了则使小球回弹,否则游戏结束 :param position:小球的坐标 ''' # 获取球拍在画布的坐标,返回一个数组(两个坐标,左上角的坐标和右下角的两个坐标) paddle_position = self.canvas.coords(self.paddle.id) print ('paddle_position:',paddle_position[0],paddle_position[1],paddle_position[2],paddle_position[3]) # 如果小球的右下角x坐标 大于等于 球拍左上角x坐标,且小球左上角x坐标 小于等于 球拍右下角x坐标 if position[2] >= paddle_position[0] and position[0] <= paddle_position[2]: # 如果小球右下角y坐标 大于等于 球拍左上角y坐标,且小球右下角y坐标 小于等于 球拍右下角坐标 if position[3] >= paddle_position[1] and position[3] <= paddle_position[3]: # 横坐标 等于 self.x += self.paddle.x colors = ['red','green'] # shuffle() 方法将序列的所有元素随机排序,以便随机获得小球颜色 random.shuffle(colors) self.color= colors[0] # self.canvas.itemconfig(self.id,fill=colors[0]) # 计算得分并展示,且同时将小球的颜色、关卡颜色同步 self.score.hit(ball_color = self.color) self.canvas.itemconfig(self.paddle.id,fill=self.color) # 增加或减少球拍的宽度 self.adjust_paddle(paddle_position) return True return False def adjust_paddle(self,paddle_position): ''' 该函数用于增加或减少球拍的宽度 :paddle_position:球拍的位置坐标 ''' # 球拍每次的增量大小 paddle_grow_length = 30 # 球拍的宽度 = 球拍的右下角x坐标 - 球拍的左上角x坐标 paddle_width = paddle_position[2] - paddle_position[0] if self.color == 'red': # 如果当前球的颜色为红色 if paddle_width > 30: # 如果球拍的宽度大于60 if paddle_position[2] >= self.canvas_width: # 如果球拍右下角的x坐标 大于等于 画布宽度 # 球拍右下角x坐标 = 球拍右下角x坐标 - 增量值 paddle_position[2] = paddle_position[2] - paddle_grow_length else: # 球拍的左上角x坐标 = 球拍的左上角x坐标 + 增量值 paddle_position[0] = paddle_position[0] + paddle_grow_length elif self.color == 'green': # 如果当前球的颜色为绿色 if paddle_width < 300: # 如果球拍的宽度小于300 if paddle_position[2] >= self.canvas_width: # 如果球拍的右下角x坐标 大于等于 画布宽度 # 球拍左上角x坐标 - 增量值 paddle_position[0] = paddle_position[0] - paddle_grow_length else: # 球拍右下角x坐标 + 增量值 paddle_position[2]=paddle_position[2]+paddle_grow_length class Paddle: ''' 球拍类 ''' def __init__(self,canvas,color): ''' :param canvas:画布 :param color:球拍的颜色 ''' self.canvas = canvas # winfo_width()函数来获取画布当前的宽度,赋值给对象变量 self.canvas_width = self.canvas.winfo_width() # winfo_height()函数来获取画布当前的高度,赋值给对象变量 self.canvas_height = self.canvas.winfo_height() # 保存tkinter画球拍时返回的id,为后期移动屏幕上的球拍做准备, # create_rectangle 画矩形,fill为球拍的颜色 self.id = canvas.create_rectangle(0,0,180,15,fill=color) # 将球拍移动至初始位置 self.canvas.move(self.id,200,self.canvas_height*0.75) # 设置对象变量x,初始值为0.也就是球拍先不移动 self.x = 0 # 游戏是否开始,默认为Flase,即 不开始 self.started = False # 是否继续游戏,默认值为 否 self.continue_game = False # 初始化时将事件‘按下左键'和函数向左移动绑定 self.canvas.bind_all('<KeyPress-Left>',self.turn_left) # 初始化时将事件‘按下右键'和函数向右移动绑定 self.canvas.bind_all('<KeyPress-Right>',self.turn_right) # 初始化时将事件‘按下Enter键'和函数继续游戏绑定 self.canvas.bind_all('<KeyPress-Enter>',self.continue_game) # 按任意键开始游戏 self.canvas.bind_all('<Button-1>',self.start_game) # 初始化时将事件‘按下space键'和函数暂停游戏绑定 self.canvas.bind_all('<space>',self.pause_game) def turn_left(self,event): ''' 该函数用于向左移动时, ''' # 获取球拍的位置坐标 position = self.canvas.coords(self.id) # 如果球拍的左上角x坐标 小于 0 if position[0] <= 0: # 则再次按向左移动时,移动距离为0 self.x = 0 else: # 每次向左移动3个像素 self.x = -3 def turn_right(self,event): # 获取球拍的位置坐标 position = self.canvas.coords(self.id) # 如果球拍的右下角x坐标 大于等于 画布宽度 if position[2] >= self.canvas_width: # 则再次按向右移动时,移动距离为0 self.x = 0 else: # 每次向右移动3个像素 self.x = 3 def start_game(self,evt): self.started = True def pause_game(self,evt): if self.started: self.started=False else: self.started=True def draw(self): ''' 该函数用于移动球拍 ''' # 球拍类可以水平移动 self.canvas.move(self.id,self.x,0) # 获取球拍的位置坐标 position = self.canvas.coords(self.id) # 如果球拍左上角x坐标小于等于0,则停止移动 if position[0] <= 0: self.x = 0 # 如果球拍右下角x坐标大于等于0,则停止移动 elif position[2] >= self.canvas_width: self.x = 0 class Score(): ''' 得分类 ''' def __init__(self,canvas,color): ''' 初始化得分类 :param canvas:画布 :param color:得分文本的颜色 ''' # 初始化得分为0 self.score = 0 # 把参数canvas赋值给对象变量canvas self.canvas = canvas # winfo_width()函数来获取画布当前的宽度,赋值给对象变量 self.canvas_width = self.canvas.winfo_width() # winfo_height()函数来获取画布当前的高度,赋值给对象变量 self.canvas_height = self.canvas.winfo_height() # 创建文本控件,用户保存用户保存得分 self.id = canvas.create_text(self.canvas_width-150,10,text='score:0',fill=color,font=(None, 18, "bold")) # 用户保存游戏的关卡颜色 self.note = canvas.create_text(self.canvas_width-70,10,text='--',fill='red',font=(None, 18, "bold")) def hit(self,ball_color='grey'): ''' 该函数用于将计算得分并展示,且同时将小球的颜色、关卡颜色同步 :param ball_color:小球的颜色,默认为'grey' ''' # 得分递增 self.score += 1 # 将得分展示在文本控件中 self.canvas.itemconfig(self.id,text='score:{}'.format(self.score)) # 将小球的颜色同步至游戏关卡的颜色 if ball_color == 'red': self.canvas.itemconfig(self.note,text='{}-'.format('W'),fill='red') elif ball_color=='green': self.canvas.itemconfig(self.note,text='{}+'.format('W'),fill='green') else: self.canvas.itemconfig(self.note,text='--',fill='grey') def main(): # tkinter.Tk()类创建一个tk对象,它就是一个基本窗口,可以在其上增加其他东西 tk = tkinter.Tk() # call back for Quit def callback(): ''' 该函数用于,当点击窗口 关闭 按钮时,展示一个消息提示框,询问是否要关闭, 点击 是,则退出窗口 ''' if mb.askokcancel("Quit", "Do you really wish to quit"): # Ball.flag = False tk.destroy() # 使用protocol将 WM_DELETE_WINDOW 与 callback 绑定,程序在退出时打印 'WM_DELETE_WINDOW' tk.protocol("WM_DELETE_WINDOW", callback) # 画布的宽 canvas_width = 600 # 画布的高 canvas_hight = 500 # 窗口标题 tk.title("Ball Game V1.2") # 窗口不可被拉伸,(0,0)的意思是“窗口的大小在水平方向上和垂直方向上都不能改变” tk.resizable(0,0) # 调用wm_attributes,将窗口始终放到所有其他窗口之前(-topmost),将1改为0画布窗口不在其他窗口之前 tk.wm_attributes("-topmost",1) # 创建画布,bd=0,highlightthickness=0 作用是画布之外没有边框,可以使游戏屏幕看上去更加美观。最后一个bd是画布的背景色。 canvas = tkinter.Canvas(tk,width=canvas_width,height=canvas_hight,bd=0,highlightthickness=0,bg='#00ffff') # 按照上面一行指定的宽度高度参数调整其自身大小 canvas.pack() # update强制更新屏幕,实时更新画布 tk.update() # 创建得分类,得分控件的颜色为红色 score = Score(canvas,'red') # 创建 球拍类, paddle = Paddle(canvas,"red") # 创建 小球类,小球的默认颜色为灰色 ball = Ball(canvas,paddle,score,"grey") # 游戏结束时的提示 game_over_text = canvas.create_text(canvas_width/2,canvas_hight/2,text='Game over',state='hidden',fill='red',font=(None, 18, "bold")) # 游戏开始时的提示 introduce = 'Welcome to Ball GameV1.2:\nClick Any Key--Start\nStop--Enter\nContinue-Enter\n' game_start_text = canvas.create_text(canvas_width/2,canvas_hight/2,text=introduce,state='normal',fill='magenta',font=(None, 18, "bold")) # 主循环,让tkinter不停地重画屏幕 while True: # 如果小球没有碰到了底部,且 游戏尚未开始 if (ball.hit_bottom == False) and ball.paddle.started: canvas.itemconfig(game_start_text,state='hidden') ball.draw() paddle.draw() # 如果小球碰到了底部,则游戏结束 if ball.hit_bottom == True: time.sleep(0.1) canvas.itemconfig(game_over_text,state='normal') # 不停的刷新画布 tk.update_idletasks() # 强制更新屏幕 tk.update() time.sleep(0.01) if __name__=='__main__': main()
以上就是python 实现弹球小游戏的详细内容,更多关于python 弹球游戏的资料请关注其它相关文章!
DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米
暂无评论...
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
2024年11月24日
2024年11月24日
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]