大家好,我是涵子。今天我为大家带来pygame-pymunk的台球游戏!
友情提醒:
如果不认识pymunk的同学可以去看看之前的文章:
python-编程宇宙-计算机网络的宇宙希望大家可以更加了解pymunk!
目录
一、前面准备
二、中间程序
三、最后程序
四、效果图
五、完整代码
六、总结
一、前面准备
和之前一样,就是加了一个pymunk和一些变量:
- # -coding utf-8 -
- # import pygame, pymunk and sys
- import pygame as pg
- import pymunk as pm
- import sys
-
- # init program
- pg.init()
- # set screen
- screen = pg.display.set_mode((800, 500)) # cannot change the size of the screen
- # set title
- pg.display.set_caption("Billiards", "4.0")
-
- # pymunk Space
- space = pm.Space()
- # gravity
- # gravity and speed
- space.gravity = (0, 0) # gravity = 0
-
- # colors for draw
- white = (236, 240, 241) # white
- gray = (123, 125, 125) # gray
- stage = (51, 51, 51) # stage
-
- points = [""] * 16 # particleBalls
-
- balls = [""] * 16 # rigid bodies
-
- y = 0 # Ypos
-
- x = 0 # Xpos
-
- n = 5 # create n
-
- # colors, use for balls
- colors = ["yellow", "blue", "red", "purple", "orange", "green", "brown", "black",
- "yellow", "blue", "red", "purple", "orange", "green", "brown","white"]
pymunk.sapce和gravity是啥?没事,我们来看看:
这就是用pymunk做的一个程序。之前的文章里有代码。
space就是指一个空间,gravity就是重力。我们不需要重力。
二、中间程序
- # def draw
- def draw():
- # screen fill
- screen.fill(white)
- # draw stage
- pg.draw.line(screen, gray, (0, 250), (800, 250), 500)
- pg.draw.line(screen, stage, (20, 250), (780, 250), 460)
- # draw a ball in the pygame, pos is the points' and balls'
- # make the ball has gravity
- # show the ball
- # use range
- for i in range(16):
- # if it appears, then--
- # if it doesn't, don't draw it, or system wrong
- if points[i]:
- # --draw circle
- pg.draw.circle(screen, colors[i], points[i].position, 10)
- # update space, can change ball's position
- space.step(0.2) # use space.step
-
- # create holes this list
- holes = [(20,20),(400,20),(780,20),(20,480),(400,480),(780,480)]
-
- # def drawHole
- def drawHole():
- # use loop
- for h in holes:
- # draw circle
- pg.draw.circle(screen,'gray',h,20)
-
- # def dis
- def dis():
- # global first
- global points,balls
- # use loop
- for i,p in enumerate(points):
- # check pos
- for h in holes:
- # check
- if p and (p.position[0]-h[0])**2+(p.position[1]-h[1])**2<400:
- # make the ball disappear
- points[i] = ""
- balls[i] = ""
-
- # def friction
- def friction():
- # make the balls speed be slower and slower
- # global first!
- global points
- for v in points:
- # if v is appear
- if v:
- # then make the speed slower
- v.velocity *= 0.99
-
- # def cue
- def cue():
- # get white ball speed(velocity)
- # it is a little bit difficult
- # if abs(speed) < 0.1, the do next
- # because of there will have -num, so we need abs!
- # first need loop!
- # staticflag
- staticFlag = 1
- for i in points:
- # check
- # switch thinking is on again!
- if i and (abs(i.velocity[0]) > 0.1 or abs(i.velocity[1]) > 0.1):
- # there's a ball is running!
- staticFlag = 0
- # then check
- if points[15] and staticFlag == 1:
- # get pos
- mPos = pg.mouse.get_pos()
- # draw cue
- pg.draw.line(screen,(249,231,159),points[15].position,mPos,5)
- # get if pressed
- if pg.mouse.get_pressed()[0]:
- # move ball and cue, and boom!
- # wallop!
- points[15].apply_impulse_at_local_point(((points[15].position[0]-mPos[0]),(points[15].position[1]-mPos[1])),(0,0))
-
- # create balls
- # def create
- def create():
- # global first, or system error
- global points,balls
- # create y, x, n
- y = 0
- x = 0
- n = 5
- # create balls of particle balls and rigid bodies
- for i in range(15):
- # creat particle balls and rigid bodies
- points[i] = pm.Body(1,2000)
- points[i].position = 150+x,250+y-n*10
- balls[i] = pm.Circle(points[i],10)
- # elasticity
- balls[i].elasticity = 0.95
- space.add(points[i],balls[i])
- y+=20
- # check pos
- if y>=20*n:
- # change y
- y = 0
- # change x
- x +=20
- # chang n
- n-=1
- # create white ball
- points[15] = pm.Body(1,2000)
- points[15].position = 450,250
- balls[15] = pm.Circle(points[15],10)
- balls[15].elasticity = 0.95
- space.add(points[15],balls[15])
-
- # def wall
- def wall():
- # create a wall
- # it umm... difficult, not very easy for everyone
- # it just like a air wall
- # put these static_body wall into a list
- lines = [
- pm.Segment(space.static_body,(10,10),(790,10),20),
- pm.Segment(space.static_body,(10,10),(10,490),20),
- pm.Segment(space.static_body,(790,10),(790,490),20),
- pm.Segment(space.static_body,(10,490),(790,490),20)
- ]
- # use range to check lines
- for line in lines:
- # elasticity
- line.elasticity = 1
- # friction
- line.friction = 0.9
- space.add(*lines) # add lines
额,好长是不?
没事,我慢慢讲。(此时我已经开始颤抖)
注释里有,自己去翻译吧!
首先,遇到的问题就是画画。
- # def draw
- def draw():
- # screen fill
- screen.fill(white)
- # draw stage
- pg.draw.line(screen, gray, (0, 250), (800, 250), 500)
- pg.draw.line(screen, stage, (20, 250), (780, 250), 460)
- # draw a ball in the pygame, pos is the points' and balls'
- # make the ball has gravity
- # show the ball
- # use range
- for i in range(16):
- # if it appears, then--
- # if it doesn't, don't draw it, or system wrong
- if points[i]:
- # --draw circle
- pg.draw.circle(screen, colors[i], points[i].position, 10)
- # update space, can change ball's position
- space.step(0.2) # use space.step
首先画好外面的边框,填满里面的颜色,然后再画出里面的球(后面的程序衔接上这个函数)。可是有一个问题,为什么要有if points[i],你想想,要是球掉洞里了还会出现吗?
然后面临的问题是画洞和判断球进去了没。
- # create holes this list
- holes = [(20,20),(400,20),(780,20),(20,480),(400,480),(780,480)]
-
- # def drawHole
- def drawHole():
- # use loop
- for h in holes:
- # draw circle
- pg.draw.circle(screen,'gray',h,20)
-
- # def dis
- def dis():
- # global first
- global points,balls
- # use loop
- for i,p in enumerate(points):
- # check pos
- for h in holes:
- # check
- if p and (p.position[0]-h[0])**2+(p.position[1]-h[1])**2<400:
- # make the ball disappear
- points[i] = ""
- balls[i] = ""
这里用到了enumerate,额,有难了点哈。
想让球消失,那就把i索引的东西删掉(就是变成一个空字符串)
下面就是噩梦了!(苦痛之路)
- # def friction
- def friction():
- # make the balls speed be slower and slower
- # global first!
- global points
- for v in points:
- # if v is appear
- if v:
- # then make the speed slower
- v.velocity *= 0.99
-
- # def cue
- def cue():
- # get white ball speed(velocity)
- # it is a little bit difficult
- # if abs(speed) < 0.1, the do next
- # because of there will have -num, so we need abs!
- # first need loop!
- # staticflag
- staticFlag = 1
- for i in points:
- # check
- # switch thinking is on again!
- if i and (abs(i.velocity[0]) > 0.1 or abs(i.velocity[1]) > 0.1):
- # there's a ball is running!
- staticFlag = 0
- # then check
- if points[15] and staticFlag == 1:
- # get pos
- mPos = pg.mouse.get_pos()
- # draw cue
- pg.draw.line(screen,(249,231,159),points[15].position,mPos,5)
- # get if pressed
- if pg.mouse.get_pressed()[0]:
- # move ball and cue, and boom!
- # wallop!
- points[15].apply_impulse_at_local_point(((points[15].position[0]-mPos[0]),(points[15].position[1]-mPos[1])),(0,0))
-
- # create balls
- # def create
- def create():
- # global first, or system error
- global points,balls
- # create y, x, n
- y = 0
- x = 0
- n = 5
- # create balls of particle balls and rigid bodies
- for i in range(15):
- # creat particle balls and rigid bodies
- points[i] = pm.Body(1,2000)
- points[i].position = 150+x,250+y-n*10
- balls[i] = pm.Circle(points[i],10)
- # elasticity
- balls[i].elasticity = 0.95
- space.add(points[i],balls[i])
- y+=20
- # check pos
- if y>=20*n:
- # change y
- y = 0
- # change x
- x +=20
- # chang n
- n-=1
- # create white ball
- points[15] = pm.Body(1,2000)
- points[15].position = 450,250
- balls[15] = pm.Circle(points[15],10)
- balls[15].elasticity = 0.95
- space.add(points[15],balls[15])
-
- # def wall
- def wall():
- # create a wall
- # it umm... difficult, not very easy for everyone
- # it just like a air wall
- # put these static_body wall into a list
- lines = [
- pm.Segment(space.static_body,(10,10),(790,10),20),
- pm.Segment(space.static_body,(10,10),(10,490),20),
- pm.Segment(space.static_body,(790,10),(790,490),20),
- pm.Segment(space.static_body,(10,490),(790,490),20)
- ]
- # use range to check lines
- for line in lines:
- # elasticity
- line.elasticity = 1
- # friction
- line.friction = 0.9
- space.add(*lines) # add lines
包含了摩擦力,球杆控制和墙体的定义。
看到了这里,还不点个赞?(非强迫,喜欢就点)
接下来就是干货!(此时要有bgm响起!)
和之前一样用循环遍历所有球,如果有球就减速。没有的话就跳过。接下来$%!)@(*#@$(*&
算了,我已经看见了你们满脸的疑惑。来,我还是慢慢来吧!
这里又一次运用到了开关思维。实在不行的同学直接跳过。到达最后的完整代码就可以了。
太难了是不?
接下来就是用上质点和刚体组成现实(游戏)中的球。相当于用pymunk做出原子核,用pygame泼油漆,做模型。
后面用segment和列表把墙体加入游戏。
后面就是结尾了!
三、最后程序
- # use wall
- wall()
-
- # create balls before loop, or boom, or system wrong
- create()
- # check fps and events
- fps = pg.time.Clock()
- while True:
- # tick fps
- fps.tick(60)
- # quit events
- event = pg.event.poll()
- if event.type==pg.QUIT:
- pg.quit()
- sys.exit()
- exit()
- # main program
- dis()
- draw()
- friction()
- cue()
- drawHole()
- # display program
- pg.display.update()
好像平平无奇是吗?挺简单的是吗?额,的确是的。
就是调用函数,检查程序退出。
四、效果图
牛皮吧?
五、完整代码
附上完整代码:
- # -coding utf-8 -
- # import pygame, pymunk and sys
- import pygame as pg
- import pymunk as pm
- import sys
-
- # init program
- pg.init()
- # set screen
- screen = pg.display.set_mode((800, 500)) # cannot change the size of the screen
- # set title
- pg.display.set_caption("Billiards", "4.0")
-
- # pymunk Space
- space = pm.Space()
- # gravity
- # gravity and speed
- space.gravity = (0, 0) # gravity = 0
-
- # colors for draw
- white = (236, 240, 241) # white
- gray = (123, 125, 125) # gray
- stage = (51, 51, 51) # stage
-
- points = [""] * 16 # particleBalls
-
- balls = [""] * 16 # rigid bodies
-
- y = 0 # Ypos
-
- x = 0 # Xpos
-
- n = 5 # create n
-
- # colors, use for balls
- colors = ["yellow", "blue", "red", "purple", "orange", "green", "brown", "black",
- "yellow", "blue", "red", "purple", "orange", "green", "brown","white"]
-
- # def draw
- def draw():
- # screen fill
- screen.fill(white)
- # draw stage
- pg.draw.line(screen, gray, (0, 250), (800, 250), 500)
- pg.draw.line(screen, stage, (20, 250), (780, 250), 460)
- # draw a ball in the pygame, pos is the points' and balls'
- # make the ball has gravity
- # show the ball
- # use range
- for i in range(16):
- # if it appears, then--
- # if it doesn't, don't draw it, or system wrong
- if points[i]:
- # --draw circle
- pg.draw.circle(screen, colors[i], points[i].position, 10)
- # update space, can change ball's position
- space.step(0.2) # use space.step
-
- # create holes this list
- holes = [(20,20),(400,20),(780,20),(20,480),(400,480),(780,480)]
-
- # def drawHole
- def drawHole():
- # use loop
- for h in holes:
- # draw circle
- pg.draw.circle(screen,'gray',h,20)
-
- # def dis
- def dis():
- # global first
- global points,balls
- # use loop
- for i,p in enumerate(points):
- # check pos
- for h in holes:
- # check
- if p and (p.position[0]-h[0])**2+(p.position[1]-h[1])**2<400:
- # make the ball disappear
- points[i] = ""
- balls[i] = ""
-
- # def friction
- def friction():
- # make the balls speed be slower and slower
- # global first!
- global points
- for v in points:
- # if v is appear
- if v:
- # then make the speed slower
- v.velocity *= 0.99
-
- # def cue
- def cue():
- # get white ball speed(velocity)
- # it is a little bit difficult
- # if abs(speed) < 0.1, the do next
- # because of there will have -num, so we need abs!
- # first need loop!
- # staticflag
- staticFlag = 1
- for i in points:
- # check
- # switch thinking is on again!
- if i and (abs(i.velocity[0]) > 0.1 or abs(i.velocity[1]) > 0.1):
- # there's a ball is running!
- staticFlag = 0
- # then check
- if points[15] and staticFlag == 1:
- # get pos
- mPos = pg.mouse.get_pos()
- # draw cue
- pg.draw.line(screen,(249,231,159),points[15].position,mPos,5)
- # get if pressed
- if pg.mouse.get_pressed()[0]:
- # move ball and cue, and boom!
- # wallop!
- points[15].apply_impulse_at_local_point(((points[15].position[0]-mPos[0]),(points[15].position[1]-mPos[1])),(0,0))
-
- # create balls
- # def create
- def create():
- # global first, or system error
- global points,balls
- # create y, x, n
- y = 0
- x = 0
- n = 5
- # create balls of particle balls and rigid bodies
- for i in range(15):
- # creat particle balls and rigid bodies
- points[i] = pm.Body(1,2000)
- points[i].position = 150+x,250+y-n*10
- balls[i] = pm.Circle(points[i],10)
- # elasticity
- balls[i].elasticity = 0.95
- space.add(points[i],balls[i])
- y+=20
- # check pos
- if y>=20*n:
- # change y
- y = 0
- # change x
- x +=20
- # chang n
- n-=1
- # create white ball
- points[15] = pm.Body(1,2000)
- points[15].position = 450,250
- balls[15] = pm.Circle(points[15],10)
- balls[15].elasticity = 0.95
- space.add(points[15],balls[15])
-
- # def wall
- def wall():
- # create a wall
- # it umm... difficult, not very easy for everyone
- # it just like a air wall
- # put these static_body wall into a list
- lines = [
- pm.Segment(space.static_body,(10,10),(790,10),20),
- pm.Segment(space.static_body,(10,10),(10,490),20),
- pm.Segment(space.static_body,(790,10),(790,490),20),
- pm.Segment(space.static_body,(10,490),(790,490),20)
- ]
- # use range to check lines
- for line in lines:
- # elasticity
- line.elasticity = 1
- # friction
- line.friction = 0.9
- space.add(*lines) # add lines
-
- # use wall
- wall()
-
- # create balls before loop, or boom, or system wrong
- create()
- # check fps and events
- fps = pg.time.Clock()
- while True:
- # tick fps
- fps.tick(60)
- # quit events
- event = pg.event.poll()
- if event.type==pg.QUIT:
- pg.quit()
- sys.exit()
- exit()
- # main program
- dis()
- draw()
- friction()
- cue()
- drawHole()
- # display program
- pg.display.update()
六、总结
通过这次学习和实践,我们更加了解了pymunk和pygame,认识到了python的强大。
最后,我希望大家:点个赞!关注一下。
我将持续更新关于编程的优质文章。希望大家可以和我一起学习知识,一起领略知识的力量!