大家好,我是涵子。今天我为大家带来pygame-pymunk的台球游戏!

友情提醒:

如果不认识pymunk的同学可以去看看之前的文章:

python-编程宇宙-计算机网络的宇宙https://blog.csdn.net/B20111003/article/details/125540816?spm=1001.2014.3001.5502希望大家可以更加了解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的强大。

最后,我希望大家:点个赞!关注一下。

我将持续更新关于编程的优质文章。希望大家可以和我一起学习知识,一起领略知识的力量!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐