1.前言
游戏,大家一定不陌生,那么有没有想过游戏是怎么做出来的呢?作为一个与代码打交道的人,都知道是用一行一行代码堆积出来的。今天,大家就跟小编一起来用代码敲出一款属于自己的游戏吧!
2.准备
今天要做的是一款类似于打乒乓球的小游戏,要做这款游戏必须要有一定python基础,当然只要用心,小白也是可以学会的。
小编将通过以下几个步骤来做这款游戏:
(1)配置环境
(2)设置背景
(3)绘制玩家
(4)方向控制
(5)添加乒乓球
(6)边界判断以及接球检测
(7)分数设置
3.游戏制作
1.配置环境。
首先安装python环境。详情见python官网。
(https://www.python.org/)
这款游戏用到的只有一个工具就是python的“小海龟”——turtle,这是python的内置库。只需要调用就行。这里将turtle调用为t,方便后续使用。
import turtle as t |
2.设置背景。
设置背景之前,先想一想背景需要有什么特征。自然是要有宽和高、还有标题、颜色。这里就需要用到turtle的函数,具体看代码。
game = t.Screen() #绘制游戏框 game.title('八里公路打乒乓') game.bgcolor('black') game.setup(800,600) #宽和高 |
3.绘制玩家。
同样,绘制玩家时,也需要知道玩家的特征。就是大小、颜色、形状、还有位置。这里需要注意的是turtle的坐标系是怎样的。它同pygame(python的游戏库)不一样的是,它的画布的正中央为坐标原点,所以玩家的位置就要根据玩家大小和游戏窗口大小来计算得出。还有由于玩家是可以移动的,所以其坐标就不能写死,就用两个变量x,y来表示。详见代码。
p1 = t.Turtle() p1.ht() #隐藏画笔的标识 p1.up() #提起画笔,防止移动时留下痕迹 p1.color('yellow') p1.speed(5) #移动速度 p1.shape('square') #玩家形状 p1.shapesize(5,1) #大小长宽为5:1 p1.goto(-350,0) p1.st() p1_score = 0 #玩家1的得分,后续会用 def p1_up(): #移动的方法,后面可以直接调用 y = p1.ycor() y += 20 p1.sety(y) def p1_down(): y = p1.ycor() y -= 20 p1.sety(y) |
同理,再绘制出玩家2.这里先看一下效果;
图1玩家绘制效果
4.方向控制。
要控制方向,就需要程序知道键盘动作,所以turtle中有一个listen()函数,可以知道键盘上的动作,具体的哪个按键控制什么动作,都是可以自己设置的。
game.listen() game.onkey(p1_up,'s') #移动方向对应按键的设置 game.onkey(p1_down,'x') #对应的移动在绘制玩家代码中,调用移动方法。 game.onkey(p2_up,'Up') game.onkey(p2_down,'Down') |
注意:在游戏时,只有英文输入法键盘才能控制。
5.添加乒乓球。
添加方法和添加玩家是一样的,不同的是其形状为圆形,位置也要注意,既然是双人游戏,为了公平起见,选择在窗口中心坐标原点出发球。一样要注意坐标不能写死了,也用两个变量表示。还有乒乓球是自己动的,所以还需要给它一个移动“规则”,也就是dx,和dy,这样就是沿着一条斜线移动的。
pp = t.Turtle() pp.up() pp.color('white') pp.speed(0) pp.shape('circle') pp.st() pp.dx = 3 pp.dy = 3 pp.setx(pp.xcor()+pp.dx) #位置移动 pp.sety(pp.ycor()+pp.dy) |
6.边界判断以及接球检测。上述步骤都是比较容易的,没有什么逻辑关系,关键在于对turtle的用法掌握。而这一步骤就需要比较强的编程思维以及一定数学能力了。由于玩家是可以自己移动的,所以就不用管玩家的界限。对于乒乓球而言,它首先是从原点往右上方移动,最先会撞到上方的边界,根据物理的光学反射原理,可以得出球撞到上边界时会以它的入射角度反方向移动,放到坐标系上来看,就是横坐标不变,被反弹回来后其纵坐标变为相反数,所以只需要将乒乓球的移动规则的dy乘上-1就可以了。同理,下边界也是一样的道理。至于坐标的范围就需要自己在纸上画一画了。
pp.setx(pp.xcor()+pp.dx) #位置移动 pp.sety(pp.ycor()+pp.dy) if pp.ycor() > 290 or pp.ycor() < -290: #上下边界范围 pp.dy *= -1 |
判断了上下边界,然后再判断左右边界,跟上下边界判断方法一样,不同的是球左右出界后不会反弹。而是回到原点重新开始。
if pp.xcor()>380: #右边界范围 pp.goto(0,0) p1_score += 1 #球在哪一边出界了,它的对手就加以分。 score() if pp.xcor()<-380: #左边界范围 pp.goto(0,0) p2_score += 1 score() |
再来看接球检测,如果球的坐标与球拍的坐标距离在一定的范围内了,就要让球反弹,dy不变,dx乘上-1。为了防止球在球拍上的粘连情况,让球反弹时适当往球拍外移动一点,这里选择将球的横坐标改变为339或-339.
if pp.ycor()<p2.ycor()+50 and pp.ycor()>p2.ycor()-50 and pp.xcor()>340: pp.dx *= -1 pp.setx(339) if pp.ycor()<p1.ycor()+50 and pp.ycor()>p1.ycor()-50 and pp.xcor()<-340: pp.dx *= -1 pp.setx(-339) |
7.分数设置。可以直接用turtle的write()函数,然后再自己设置字的颜色,大小,位置。
def score(): pen.clear() #防止叠加 pen.write('八里公路:%d VS 大魔王:%d' % (p1_score,p2_score),align='center',font=('Arial',20,'bold')) score() |
特别注意的是,由于turtle的工作原理是一遍一遍的画,所以需要定义一个主循环,让需要的一直出现在窗口中。还要防止文字叠加,所以每一画的时候,都要清空画笔,然后update更新。
#判断是否退出 running = True def stop_loop(): global running running = False #注册退出事件 root = game.getcanvas().winfo_toplevel() root.protocol('WM_DELETE_WINDOW',stop_loop) while running: game.update() |
上面的几个看不懂的东西,只需要记住就行了,它的目的是让电脑知道叉掉窗口是要退出游戏的意思,这样才退出时不会报错。
4.综合代码
经过以上所有步骤,这个游戏就算是做好了,来看一下完整代码吧。
import turtle as t #设置背景 game = t.Screen() #绘制游戏框 game.title('八里公路打乒乓') game.bgcolor('black') game.setup(800,600) #宽和高 game.tracer() #玩家1 p1 = t.Turtle() p1.ht() #隐藏画笔的标识 p1.up() #提起画笔,防止移动时留下痕迹 p1.color('yellow') p1.speed(5) #移动速度 p1.shape('square') #玩家形状 p1.shapesize(5,1) #大小长宽为5:1 p1.goto(-350,0) p1.st() p1_score = 0 #玩家1的得分,后续会用 def p1_up(): #玩家1的坐标,移动时使用,这里是向上 y = p1.ycor() y += 20 #移动步长 p1.sety(y) def p1_down(): #对应的移动在绘制玩家代码中,调用移动方法。 y = p1.ycor() y -= 20 p1.sety(y) #玩家2 p2 = t.Turtle() p2.ht() p2.up() p2.color('red') p2.speed(5) p2.shape('square') p2.shapesize(5,1) p2.goto(350,0) p2.st() p2_score = 0 def p2_up(): y = p2.ycor() y += 20 p2.sety(y) def p2_down(): y = p2.ycor() y -= 20 p2.sety(y) #添加乒乓 pp = t.Turtle() pp.up() pp.color('white') pp.speed(0) pp.shape('circle') pp.st() pp.dx = 3 pp.dy = 3 #添加分数 pen = t.Turtle() pen.ht() pen.color('white') pen.up() pen.goto(0,250) pen.down() def score(): pen.clear() #防止叠加 pen.write('八里公路:%d VS 大魔王:%d' % (p1_score,p2_score),align='center',font=('Arial',20,'bold')) score() pen1 = t.Turtle() pen1.ht() pen1.up() pen1.color('white') pen1.goto(0,220) pen1.write('左:s(上),x(下);右:方向键控制上下',align='center',font=('Arial',15,'bold')) #玩家移动 game.listen() game.onkey(p1_up,'s') #移动方向对应按键的设置 game.onkey(p1_down,'x') #对应的移动在绘制玩家代码中,调用移动方法。 game.onkey(p2_up,'Up') game.onkey(p2_down,'Down') #判断是否退出 running = True def stop_loop(): global running running = False #注册退出事件 root = game.getcanvas().winfo_toplevel() root.protocol('WM_DELETE_WINDOW',stop_loop) #乒乓移动 while running: game.update() pp.setx(pp.xcor()+pp.dx) #位置移动 pp.sety(pp.ycor()+pp.dy) if pp.ycor() > 290 or pp.ycor() < -290: pp.dy *= -1 #接球 if pp.ycor()<p2.ycor()+50 and pp.ycor()>p2.ycor()-50 and pp.xcor()>340: pp.dx *= -1 pp.setx(339) if pp.ycor()<p1.ycor()+50 and pp.ycor()>p1.ycor()-50 and pp.xcor()<-340: pp.dx *= -1 pp.setx(-339) #球出界 if pp.xcor()>380: #右边界范围 pp.goto(0,0) p1_score += 1 score() if pp.xcor()<-380: #左边界范围 pp.goto(0,0) p2_score += 1 score() |
然后再看以下运行效果。
图2 最终效果
5.总结
做完这个简单的游戏后,不知道大家对写代码有了什么新的看法?
当然做游戏不是主要目的,只是通过做游戏来感受以下编程带来的乐趣,毕竟可视化后是要比代码有趣多了。而且,大家也看到了,仅仅是这样一个简单的游戏,也是需要不少功夫的,所以,在编游戏的同时也能提高编程思维,以及解决问题的方法步骤。那么,你是不是也想跟小编一起做做小游戏呢?