大家好,我是涵子。今天我为大家带来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的强大。
最后,我希望大家:点个赞!关注一下。
我将持续更新关于编程的优质文章。希望大家可以和我一起学习知识,一起领略知识的力量!
|