Tabla de contenido
1. Una breve descripción de las reglas
(1) Sobre el funcionamiento de la pelota
(2) Sobre la adición de IA para personas con discapacidades mentales
(3) Embellecimiento de la interfaz
(4) Agregue efectos de sonido de fondo y música
Prefacio:
Este sigue siendo un proyecto en el plan de estudios de mi escuela, porque también tengo que tomar el examen de ingreso de posgrado, por lo que no dediqué demasiado tiempo a hacer buenos proyectos. Entonces hice algunas mejoras simples basadas en un juego de tenis de mesa en Internet. Los siguientes son los documentos y las direcciones de descarga del código fuente a los que me refiero, y puede recogerlos si los necesita:
Si quieres entender el proyecto que estoy haciendo, finalmente puedes leer el siguiente documento, que introduce su lógica de funcionamiento más básica:
Tutorial del juego Pong: documentación de Kivy 2.1.0 https://kivy.org/doc/stable/tutorials/pong.html
1. Una breve descripción de las reglas
(1) Acerca de la colisión
Como todos sabemos, la lógica de colisión del juego de pinball: cuando la bola golpea el tablero o el límite, rebota, la velocidad vertical se invierte cuando golpea los límites superior e inferior, y la velocidad horizontal se invierte cuando golpea los límites izquierdo y derecho.
(2) Acerca de la puntuación
Hay varias reglas de puntuación. En primer lugar, puede definir agregar puntos cuando toca el tablero, o puede agregar puntos al oponente cuando toca el borde de su propio lado, etc. También se pueden establecer puntos.
2. Mejoras a las reglas
(1) Sobre el funcionamiento de la pelota
El proceso de carrera de la pelota es lógico, lo que hará que el jugador prediga la dirección de la pelota al jugar, lo que reduce en gran medida la dificultad, por lo que configuré una lógica de carrera irregular aquí, y la velocidad de la pelota y el tamaño cambiarán. aleatoriamente a lo largo del tiempo. Vamos a explicarlo con código:
Primero definí algunos parámetros para facilitar los cambios posteriores en la velocidad y el tamaño:
speed_x = NumericProperty(0) # 球的水平速度属性
speed_y = NumericProperty(0) # 球的垂直速度属性
speed = ReferenceListProperty(speed_x, speed_y) # 球的速度向量属性
r = NumericProperty(0) #球的大小属性
max_speed = 5 # 球的最大速度
A continuación, la función de movimiento actualiza la posición de la pelota en tiempo real. La función aleatoria significa que la velocidad de la pelota cambia constantemente. Los números positivos de vel_y y vel_x representan las velocidades hacia arriba y hacia la derecha, y los números negativos son viceversa. La función daxiao hace que la bola cambie aleatoriamente entre 20*20 y 80*80.
def move(self):
self.pos = Vector(*self.speed) + self.pos # 根据速度更新球的位置
def randomize(self):
# 随机化速度
vel_x = uniform(-5, 5) # 在[-5, 10]范围内生成一个随机数作为水平速度
vel_y = uniform(-5, 5) # 垂直速度
self.speed = Vector(vel_x, vel_y).normalize() * self.max_speed # 设置球的速度向量,并将其归一化后乘以最大速度
def daxiao(self):
# 随机化大小
r = uniform(20, 80)
self.size = r , r # 在[20, 80]范围内生成一个随机数作为球的大小
print(self.size)
Luego llámalo en la clase subsiguiente.
def serve_ball(self):
self.ball.center = self.center # 将球的中心位置设置为窗口的中心位置
self.ball.randomize() # 随机化球的速度
self.ball.daxiao() # 随机化球的大小
self.timer = 0 # 计时器初始化为0
(2) Sobre la adición de IA para personas con discapacidades mentales
¿Por qué se llama IA para discapacitados mentales? Como sugiere el nombre, su lógica de implementación es demasiado simple. Solo necesitamos dejar que el centro de uno de los tableros se mueva con el centro de la pelota y establecer la velocidad de carrera. ¿No es así? muy simple Ababa (• • )~
def move_player2(self):
# 根据球的位置移动玩家2的挡板
if self.ball.center_y < self.player2.center_y:
self.player2.center_y -= 5 # 将玩家2的挡板向下移动5个单位
elif self.ball.center_y > self.player2.center_y:
self.player2.center_y += 5
Entonces recuerda llamarlo al frente, para que el tablero se mueva con nuestra bola, para que no tengas que controlar a dos jugadores tú solo. Por supuesto, también puede configurar el tablero del jugador 1 en automático, para que pueda ver los dos tableros y jugar solo.
(3) Embellecimiento de la interfaz
Con respecto al embellecimiento de la interfaz, modificamos principalmente el archivo kv. El siguiente es mi archivo kv completo. Podemos configurar el tamaño, el color, etc. Para los parámetros específicos, puede consultarlo en línea.
<PongBall>:
canvas:
Color:
rgba: .9,.9,.1 ,9
Ellipse:
pos: self.pos
size: self.size
source: "出生.jpg"
<PongPaddle>:
size: 25, 150
canvas:
Color:
rgba: 1, 1, 1, .9
Rectangle:
pos: self.pos
size: self.size
source: "无标题.png"
<PongGame>:
ball: pong_ball
player1: player_left
player2: player_right
canvas:
Color:
rgba:1, 1, 1, .9
Rectangle:
size:self.size
source:"233.jpg"
Color:
rgba: .2, 1, 1, .9
Rectangle:
pos: self.center_x - 5, 0
size: 10, self.height
Label:
color: .9,.6,.1 ,9
font_size: 70
center_x: root.width / 4
top: root.top - 50
text: str(root.player2.score)
Label:
color: .8,.1,.1 ,9
font_size: 70
center_x: root.width * 3/4
top: root.top - 50
text: str(root.player1.score)
PongBall:
id: pong_ball
center: self.parent.center
PongPaddle:
id: player_left
x: root.x
center_y: root.center_y
PongPaddle:
id: player_right
x: root.width - self.width
center_y: root.center_y
Aquí hay algunas fotos que usé:
El efecto final de la interfaz es el siguiente:
(4) Agregue efectos de sonido de fondo y música
Para agregar efectos de sonido y música, usaremos una biblioteca de kivy:
from kivy.core.audio import SoundLoader
Solo necesitamos las siguientes líneas de código:
sound = SoundLoader.load('away.mp3')
if sound:
sound.loop = True # 设置循环播放
sound.play()
3. Énfasis en otros detalles
(1) componente de widget
1. Widget no es un diseño y Widget no cambiará la posición y el tamaño de sus subcomponentes.
2. El tamaño predeterminado de Widget es 100*100.
3. Por defecto, el size_hint del Widget es 1 * 1. Si su componente principal es un componente de diseño, su tamaño es el tamaño requerido por el diseño en el componente principal.
4. Las funciones como on_touch_down(), on_touch_move(), on_touch_up() no realizan juicios de rango de límites de componentes (juicios de colisión) y necesitan llamar a collide_point().
(2) Lonas y etiquetas en kv
Canvas: Cree un lienzo, las siguientes son algunas propiedades de Canvas:
1 .add(): agrega un objeto gráfico al lienzo, que puede ser un gráfico o un grupo.
2. insert(): inserta un objeto gráfico antes de la posición especificada en el lienzo.
3. remove(): Elimina el objeto gráfico especificado del lienzo.
4. clear(): elimina todos los objetos gráficos del lienzo.
5. tamaño: El tamaño del lienzo, su valor determina el tamaño del lienzo.
6. pos: la posición del lienzo, su valor determina la posición del lienzo en relación con el control principal.
7. opacidad: La opacidad del lienzo, su valor está entre 0-1.
8. canvas.before: Objetos gráficos dibujados antes de todos los elementos en el lienzo.
9. canvas.after: objetos gráficos dibujados después de todos los elementos del lienzo.
10. canvas.clear(): Limpia todo el lienzo.
11. canvas.ask_update(): Actualiza a la fuerza el contenido del lienzo.
12. canvas.export_to_png(): guarde el lienzo en un archivo PNG.
Etiqueta de etiqueta: en Kivy, el widget de etiqueta se usa para presentar texto. Solo admite cadenas codificadas en ASCII y Unicode (no se admite el chino). En Etiqueta, puede configurar el contenido del texto, la fuente, el tamaño, el color, la alineación y el salto de línea. , citas y texto etiquetado
1. texto: el texto que muestra la etiqueta
2. text_size: tamaño del texto de la etiqueta
3. font_name: el nombre de archivo de la fuente que se utilizará
4. font_size: el tamaño de fuente del texto
5. negrita: la fuente usa negrita
6. cursiva: la fuente usa cursiva
7. color: color de fuente, el formato es rgba, el valor predeterminado es blanco [1, 1, 1, 1]
8. halign: la alineación horizontal del texto, los parámetros opcionales son: izquierda, centro, derecha, justificar
9. valign: la alineación vertical del texto, los parámetros opcionales son: inferior, medio (o centro), superior
10. marcado: si dividir todo el texto marcado
11. subrayar: añade un subrayado al texto
12. padding_x: el relleno horizontal del texto dentro del cuadro del widget
13. padding_y: el relleno vertical del texto dentro del cuadro del widget
14. textura: el objeto de textura del texto, el texto se representará automáticamente cuando cambie la propiedad
15. Tamaño de textura del texto textura_tamaño, determinado por el tamaño de fuente y el texto
16. tachado: agrega un tachado al texto
17. strip: Ya sea para eliminar espacios y saltos de línea
18. outline_color: el color del contorno del texto
19. outline_width: el ancho del contorno alrededor del texto, en píxeles
20. max_line: el número máximo de líneas a usar, el valor predeterminado es 0, lo que significa ilimitado
21. acortar: si el contenido del texto debe acortarse tanto como sea posible, el valor predeterminado es Falso
22. shorten_from: en qué lado acortar el texto, el valor predeterminado es el centro, los parámetros opcionales son: izquierda, derecha y centro
23. is_shortend: si renderizar de forma abreviada
24. line_height: la altura de línea del texto, el valor predeterminado es 1.0
4. Código completo
Tenga en cuenta que lo he escrito en detalle para todos, si tiene alguna pregunta, puede dejar un mensaje en cualquier momento para hacer preguntas o chatear conmigo en privado.
codigo py:
from random import randint, uniform # 导入randint和uniform函数用于生成随机数
from kivy.app import App # 导入App类,用于创建应用
from kivy.clock import Clock # 导入Clock类,用于调度函数的定时器
from kivy.core.audio import SoundLoader
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty # 导入各种属性类,用于定义属性
from kivy.uix.widget import Widget # 导入Widget类,用于创建控件
from kivy.vector import Vector # 导入Vector类,用于处理向量运算
from kivy.core.window import Window
class PongPaddle(Widget):
score = NumericProperty(0) # 分数属性,用于记录得分
def bounce_ball(self, ball):
if self.collide_widget(ball): # 如果球与挡板相撞
ball.speed_x *= -1.1 # 改变球的水平速度,反弹出去
class PongBall(Widget):
speed_x = NumericProperty(0) # 球的水平速度属性
speed_y = NumericProperty(0) # 球的垂直速度属性
speed = ReferenceListProperty(speed_x, speed_y) # 球的速度向量属性
r = NumericProperty(0) #球的大小属性
max_speed = 5 # 球的最大速度
def move(self):
self.pos = Vector(*self.speed) + self.pos # 根据速度更新球的位置
def randomize(self):
# 随机化速度
vel_x = uniform(-5, 5) # 在[-5, 10]范围内生成一个随机数作为水平速度
vel_y = uniform(-5, 5) # 垂直速度
self.speed = Vector(vel_x, vel_y).normalize() * self.max_speed # 设置球的速度向量,并将其归一化后乘以最大速度
def daxiao(self):
# 随机化大小
r = uniform(20, 80)
self.size = r , r # 在[20, 80]范围内生成一个随机数作为球的大小
print(self.size)
class PongGame(Widget):
ball = ObjectProperty(None) # 球的实例对象属性
player1 = ObjectProperty(None) # 玩家1挡板的实例对象属性
player2 = ObjectProperty(None) # 玩家2挡板的实例对象属性
music = None
def serve_ball(self):
self.ball.center = self.center # 将球的中心位置设置为窗口的中心位置
self.ball.randomize() # 随机化球的速度
self.ball.daxiao() # 随机化球的大小
self.timer = 0 # 计时器初始化为0
def update(self, dt):
self.ball.move()
if self.timer >= 3: # 如果计时器大于等于3秒
self.ball.randomize() # 随机化球的速度和大小
self.ball.daxiao()
self.timer = 0 # 重置计时器为0
else:
self.timer += dt # 更新计时器的值,增加经过的时间
# 球与上下边界的碰撞检测,如果球的底部超出窗口底部或者球的顶部超出窗口顶部
if (self.ball.y < 0) or (self.ball.top > self.height):
self.ball.speed_y *= -1 # 反转球的垂直速度,使其向相反的方向运动
# 球与左边界的碰撞检测,如果球的左边超出窗口左边界
if self.ball.x < 0:
self.ball.speed_x *= -1 # 反转球的水平速度,使其向相反的方向运动
sound1 = SoundLoader.load('你好.mp3')
if sound1:
#sound1.loop = True
sound1.play()
self.player2.score += 1 # 2 + 1
# 球与右边界的碰撞检测,如果球的右边超出窗口右边界
if self.ball.right > self.width:
self.ball.speed_x *= -1 # 反转球的水平速度,使其向相反的方向运动
sound2 = SoundLoader.load('村民叫.mp3')
if sound2:
#sound2.loop = True # 设置循环播放
sound2.play()
self.player1.score += 1 # 1 + 1
self.player1.bounce_ball(self.ball)
self.player2.bounce_ball(self.ball)
self.move_player2()
def move_player2(self):
# 根据球的位置移动玩家2的挡板
if self.ball.center_y < self.player2.center_y:
self.player2.center_y -= 5 # 将玩家2的挡板向上移动5个单位
elif self.ball.center_y > self.player2.center_y:
self.player2.center_y += 5
def on_touch_move(self, touch):
if touch.x < self.width / 1 / 4:
self.player1.center_y = touch.y # 根据触摸点的y坐标移动玩家1的挡板的中心位置
class PongApp(App):
def build(self):
self.title = '一个弹球游戏嘿嘿嘿'
game = PongGame()
game.serve_ball() # 开始游戏,将球放在中心位置并随机化速度和大小
sound = SoundLoader.load('qsbl.mp3')
if sound:
sound.loop = True # 设置循环播放
sound.play()
Clock.schedule_interval(game.update, 1.0 / 60.0) # 使用Clock类的schedule_interval方法以1/60秒的间隔调用game.update函数
return game
PongApp().run() # 创建PongApp的实例对象并运行应用程序
codigo kv:
<PongBall>:
canvas:
Color:
rgba: .9,.9,.1 ,9
Ellipse:
pos: self.pos
size: self.size
source: "出生.jpg"
<PongPaddle>:
size: 25, 150
canvas:
Color:
rgba: 1, 1, 1, .9
Rectangle:
pos: self.pos
size: self.size
source: "无标题.png"
<PongGame>:
ball: pong_ball
player1: player_left
player2: player_right
canvas:
Color:
rgba:1, 1, 1, .9
Rectangle:
size:self.size
source:"233.jpg"
Color:
rgba: .2, 1, 1, .9
Rectangle:
pos: self.center_x - 5, 0
size: 10, self.height
Label:
color: .9,.6,.1 ,9
font_size: 70
center_x: root.width / 4
top: root.top - 50
text: str(root.player2.score)
Label:
color: .8,.1,.1 ,9
font_size: 70
center_x: root.width * 3/4
top: root.top - 50
text: str(root.player1.score)
PongBall:
id: pong_ball
center: self.parent.center
PongPaddle:
id: player_left
x: root.x
center_y: root.center_y
PongPaddle:
id: player_right
x: root.width - self.width
center_y: root.center_y
5. Resumen de deficiencias
Todavía hay algunos errores, por ejemplo, si la velocidad es demasiado rápida, siempre se atascará en el borde. Para la configuración de dificultad, puede crear una interfaz de selección de dificultad, de modo que la velocidad se pueda ajustar de acuerdo con la dificultad.
Espero que esto pueda ayudar a todos ~ Si crees que te ayuda, por favor déjame un me gusta ~