Python实战案例:Python使用cocos2d实现捕鱼达人

2024-03-14 10:30

本文主要是介绍Python实战案例:Python使用cocos2d实现捕鱼达人,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Python实战案例:Python使用cocos2d实现捕鱼达人

游戏,它是一种基于物质需求满足之上的,在一些特定时间、空间范围内遵循某种特定规则的,追求精神世界需求满足的社会行为方式。合理适度的游戏允许人类在模拟环境下挑战和克服障碍,可以帮助人类开发智力、锻炼思维和反应能力。一般的小型游戏都是一些随机变化的事物,根据鼠标或键盘的操作来完成对变化事物的点击操作或者控制操作,最终实现娱乐的目的。

如下图为地铁跑酷的界面。

上图中人就是一个控制的元素,通过控制人的左右和跳跃,最终对金币进行累加的游戏。

一、游戏框架cocos2d的介绍

Cocos2D 是一个基于MIT协议的开源框架,用于构建游戏、应用程序和其他图形界面交互应用。可以让你在创建自己的多平台游戏时节省很多的时间。

Cocos2d有几个版本,python也可以安装cocos2d框架以实现游戏的开发。安装模块命令如下:

pip3 install cocos2d

在cocos2dx的开发中,导演,场景,层是必须要使用的基本元素。

在一个游戏中,导演只有一个,在程序启动的时候,会初始化一个导演,然后再由导演调用一个场景作为第一个显示的场景开启应用程序。如下图所示导演就调用了cocos2d的图标文件做为场景展示开启应用程序。

在cocos2d的每一个场景中又可以包含有多个层。

每一个层中可以包含多个精灵,控件等基本的元素,而用户看到的就是这些基本的元素。

二、Python调用cocos2d导演显示捕鱼达人背景图片的场景

现在,就要进行捕鱼达人游戏的开发,首先要有背景图片,这里为捕鱼达人的背景图片实现一个类,这个类继承于cocos2d场景的层,在初始化函数中启用导演director获取屏幕窗口的大小,实例化cocos2d中的精灵角色,并传入背景图片做为精灵,设置精灵在屏幕窗口中显的位置,背景图片一般全窗口显示,设置position中心位置为宽和高的一半,将这个层中添加这个精灵。代码如下。

class Background(cocos.layer.Layer):def __init__(self):super(Background,self).__init__()self.width,self.height=cocos.director.director.get_window_size()sprite=cocos.sprite.Sprite("textures/bg.jpg")sprite.position=self.width//2,self.height//2self.add(sprite)

把背景图片类定义成功后,在主程序中初始化导演,初始化时传入参数宽度800,高度400。接着实例化背景图类,在cocos2d的场景Scene类中传入实例化后的背景图类,最后调用cocos2d中导演的run方法运行传入参数后的实例化场景,代码如下。

import cocos
class Background(cocos.layer.Layer):def __init__(self):super(Background,self).__init__()self.width,self.height=cocos.director.director.get_window_size()sprite=cocos.sprite.Sprite("textures/bg.jpg")sprite.position=self.width//2,self.height//2self.add(sprite)
if __name__=="__main__":cocos.director.director.init(width=800,height=480);background=Background();main_scene=cocos.scene.Scene(background)cocos.director.director.run(main_scene)

运行上述程序后,显示最终捕鱼达人的背景图展示。

三、在捕鱼达人的场景中添加游动的鱼类的精灵

游戏的场景准备完毕,现在需要在捕鱼达人的场景中添加游动的鱼类,游动的鱼类图片在命名上有一些特点,每个鱼对应了10个状态的游动姿势。如下图所示的命令和简略图显示。

由图片中的内容可知,文件名中fish是所有鱼类的统一命名,紧跟其后的04就是第四种鱼类,后面再跟一条“下划线”,然后跟上“01”-“10”的数字,分别代表第四种鱼类游动过程中的状态,连续这10张图片就是第四种鱼类的游动效果。

需要说明的是,cocos2d使用pyglet来加载图片资源。pyglet模块的安装如下:

pip3 install pyglet

pyglet中resource模块可以加载需要每帧每帧进行显示的图片资源,将这些图片资源做为pyglet中resource模块的image类加入资源列表中,将此列表做为pyglet中图片image模块的Animation类的方法fromimagesequence实现从一个序列加载动画类的图片,在构建这个动画类图片之前也要构造出图片序列的图片名,将这个动画图片实现的逻辑方法封装成鱼类,这样在背景类的初始化程序中初始化鱼类,再将这个初始化的鱼类精灵添加到场景中。代码如下。

import cocos
import pyglet
class Fish(cocos.sprite.Sprite):def __init__(self):textures=[]for i in range(1,11):name_i="0"+str(i) if i<10 else str(i)fish_name_i="textures/fish04_"+name_i+".png"texture=pyglet.resource.image(fish_name_i)textures.append(texture)animation=pyglet.image.Animation.from_image_sequence(textures,0.1)super(Fish, self).__init__(animation)self.position = 500,200
class Background(cocos.layer.Layer):def __init__(self):super(Background,self).__init__()self.width,self.height=cocos.director.director.get_window_size()sprite=cocos.sprite.Sprite("textures/bg.jpg")sprite.position=self.width//2,self.height//2self.add(sprite)fish=Fish()self.add(fish)
if __name__=="__main__":cocos.director.director.init(width=800,height=480);background=Background();main_scene=cocos.scene.Scene(background)cocos.director.director.run(main_scene)

代码的运行结果如下图所示。

由图上可知,有一条鱼在屏幕中间摆动。现在就需要这条鱼能够进行游动,也就是从屏幕中的某一个点到另一个点,cocos2d中的actions模块中涉及到精灵的位置方面的运动,MoveTo完成从某一点运动到某一个点,具体格式如下。

cocos.actions.MoveTo((x轴坐标点,y辆坐标点),duration=运动的时间周期)

上面语句的运动过程需要精灵执行do语句,这样精灵就会把移动操作的方法作用到自己的身上。具体语句格式如下。

精灵.do(cocos.actions.MoveTo((x轴坐标点,y辆坐标点),duration=运动的时间周期))

根据这样的语句格式,现在将这条鱼精灵从屏幕左端移动到屏幕右端,就是初始化的时候把这条鱼精灵放在屏幕左端,然后在初始化的时候调用鱼游动的方法swim,在swim方法体中使用do语句与MoveTo语句共同作用的结果,实现鱼精灵在屏幕中从左到右的游动效果。代码如下。

import cocos
import pyglet
class Fish(cocos.sprite.Sprite):def __init__(self):textures=[]for i in range(1,11):name_i="0"+str(i) if i<10 else str(i)fish_name_i="textures/fish04_"+name_i+".png"texture=pyglet.resource.image(fish_name_i)textures.append(texture)animation=pyglet.image.Animation.from_image_sequence(textures,0.1)super(Fish, self).__init__(animation)self.position = 800,200self.swim()def swim(self):self.do(cocos.actions.MoveTo((-20,200),8))class Background(cocos.layer.Layer):def __init__(self):super(Background,self).__init__()self.width,self.height=cocos.director.director.get_window_size()sprite=cocos.sprite.Sprite("textures/bg.jpg")sprite.position=self.width//2,self.height//2self.add(sprite)fish=Fish()self.add(fish)
if __name__=="__main__":cocos.director.director.init(width=800,height=480);background=Background();main_scene=cocos.scene.Scene(background)cocos.director.director.run(main_scene)

代码中初始化时position的位置参数是(800,200),其中800是width的值,480是height的值,这两个值也是主程序中director导演初始化时决定的。代码又定义一个swim方法,在swim方法中利用do方法执行该精灵的MoveTo位置改变方法,同时在精灵类初始化方法init中也调用swim方法。

代码运行的结果如下图所示。

由运行结果图可知,一条鱼精灵会把游动的动作连贯起来,并从屏幕窗口的右边游动到屏幕窗口的左边。但是,当游动一程后,就不再游动了,往往在游戏中,我们是希望游出界的鱼类还能在另一端随机出现,这样,鱼类精灵会不停地在游戏窗口中产生,把平静的池塘背景图变得热闹起来,鱼类精灵也把捕鱼达人的界面运动了起来。那么,就在于如何将这条游出窗口界面的鱼再次显示在屏幕上,也就是不停地调用鱼游动的方法,需要在do和MoveTo共同作用的语句上加上参数+ cocos.actions.CallFunc(self.swim),这是相当于MoveTo在参数上使用了回调函数,这个回调函数的指向还是当前类中鱼精灵游动的方法。代码如下。

import cocos
import pyglet
class Fish(cocos.sprite.Sprite):def __init__(self):textures=[]for i in range(1,11):name_i="0"+str(i) if i<10 else str(i)fish_name_i="textures/fish04_"+name_i+".png"texture=pyglet.resource.image(fish_name_i)textures.append(texture)animation=pyglet.image.Animation.from_image_sequence(textures,0.1)super(Fish, self).__init__(animation)self.position = 800,200self.swim()def swim(self):self.position=800,200self.do(cocos.actions.MoveTo((-20,200),8)+ cocos.actions.CallFunc(self.swim))class Background(cocos.layer.Layer):def __init__(self):super(Background,self).__init__()self.width,self.height=cocos.director.director.get_window_size()sprite=cocos.sprite.Sprite("textures/bg.jpg")sprite.position=self.width//2,self.height//2self.add(sprite)fish=Fish()self.add(fish)
if __name__=="__main__":cocos.director.director.init(width=800,height=480);background=Background();main_scene=cocos.scene.Scene(background)cocos.director.director.run(main_scene)

代码中在鱼类精灵的swim方法中增加了一条把精灵的位置position重新调整到800,200这个位置,然后在MoveTo的action动作方法中后面再用加号加上一个callfunc回调函数,在回调方法中继续使用swim方法。

运行后,该条鱼精灵就可以一直从屏幕右端移动到屏幕左端。运行结果如下图所示。

四、游动的鱼类精灵接收鼠标事件

现在已经完成在一个捕鱼达人的池塘中有一条游动的鱼精灵,这里实现简单的捕鱼达人方法,点击这条鱼的时候,鱼就会从屏幕中消失,鱼类精灵消失的方法可以调用cocos2中对actions动作的停止方法stop(),然后调用kill()方法删除该鱼类精灵,封装在Fish中的explode方法,具体代码如下。

import cocos
import pyglet
class Fish(cocos.sprite.Sprite):def __init__(self):textures=[]for i in range(1,11):name_i="0"+str(i) if i<10 else str(i)fish_name_i="textures/fish04_"+name_i+".png"texture=pyglet.resource.image(fish_name_i)textures.append(texture)animation=pyglet.image.Animation.from_image_sequence(textures,0.1)super(Fish, self).__init__(animation)self.position = 800,200self.swim()def swim(self):self.position=800,200self.do(cocos.actions.MoveTo((-20,200),8)+ cocos.actions.CallFunc(self.swim))def explode(self):self.stop()self.kill()class Background(cocos.layer.Layer):def __init__(self):super(Background,self).__init__()self.width,self.height=cocos.director.director.get_window_size()sprite=cocos.sprite.Sprite("textures/bg.jpg")sprite.position=self.width//2,self.height//2self.add(sprite)fish=Fish()self.add(fish)
if __name__=="__main__":cocos.director.director.init(width=800,height=480);background=Background();main_scene=cocos.scene.Scene(background)cocos.director.director.run(main_scene)

这段代码中在Fish类中增加方法explode,方法体中调用stop停止动画的方法和kill删除精灵的方法。但是,目前来讲,这个explode 方法并没有被调用。所以这个鱼类精灵目前还没有办法从屏幕上消除掉。

如果要实现消除掉的效果,就需要增加一些鼠标事件,也就是需要在cocos2d的导演窗口中增加一些处理事件,window类有一个称为推处理程序的方法,它使我可以将方法推入事件堆栈。语句如下。

cocos.director.director.window.push_handlers(self.on_mouse_press)

上述代码语句中的pushhandlers就是为windows添加了一些处理,叫推处理程序,onmousepress方法是自己定义的鼠标点击方法,这个方法使用了cocos2d导演的窗口方法pushhandlers作用在了程序窗口中。此语句是定义在该对象类的onenter方法中,也就是进入到该对象的时候就会触发这样的方法。完整的onenter方法中的语句代码如下。

def on_enter(self):super(Fish, self).on_enter()cocos.director.director.window.push_handlers(self.on_mouse_press)

这里有一个回调方法onmousepress,在Fish鱼对象的精灵类中添加一个方法,其名字为onmousepress,方法体中的逻辑目前可以直接调用explode方法,也就是点击屏幕中的任何地方,都会触发鱼精灵对象的消失。代码如下。

import cocos
import pyglet
class Fish(cocos.sprite.Sprite):def __init__(self):textures=[]for i in range(1,11):name_i="0"+str(i) if i<10 else str(i)fish_name_i="textures/fish04_"+name_i+".png"texture=pyglet.resource.image(fish_name_i)textures.append(texture)animation=pyglet.image.Animation.from_image_sequence(textures,0.1)super(Fish, self).__init__(animation)self.position = 800,200self.swim()def swim(self):self.position=800,200self.do(cocos.actions.MoveTo((-20,200),8)+ cocos.actions.CallFunc(self.swim))def on_enter(self):super(Fish, self).on_enter()cocos.director.director.window.push_handlers(self.on_mouse_press)def on_mouse_press(self,x,y,button,modifier):self.explode()def explode(self):self.stop()self.kill()class Background(cocos.layer.Layer):def __init__(self):super(Background,self).__init__()self.width,self.height=cocos.director.director.get_window_size()sprite=cocos.sprite.Sprite("textures/bg.jpg")sprite.position=self.width//2,self.height//2self.add(sprite)fish=Fish()self.add(fish)
if __name__=="__main__":cocos.director.director.init(width=800,height=480);background=Background();main_scene=cocos.scene.Scene(background)cocos.director.director.run(main_scene)

代码中Fish鱼类精灵的onmousepress方法是需要4个参数的,不然运行的时候会报错。这4个参数的意义,x和y代表了鼠标点击的位置,button代表了鼠标的按键,可以通过这个参数来判断是按动了鼠标的左键还是鼠标的右键,最后的参数modifier用于描述组合键。现在运行上面的程序后。首先有一条鱼精灵从屏幕右端游动到屏幕的左端。如下图所示。

点击屏幕中任何一处的位置,都可以消除该鱼类精灵,如下图所示。

如果限制用户的坐标点只能在鱼精灵的身上才能消除该精灵,就需要通过坐标点来控制,可以可以限制当用户点击的横坐标点大于鱼的左边,小于鱼的左边坐标加上鱼的宽度,再检测纵坐标点大于鱼的上边,小于鱼的上边加上鱼的宽度,这样的判断条件可以用下图来表示:

上图对定的条件判断式为:

if x>self.x-self.width*1/2 and x<self.x+self.width*1/2 and y>self.y-self.height*1/2 and y<self.y+self.height*1/2:

把上面的点的条件判断式代码放入到onmousepress方法中,满足条件后执行explode的对象消除方法。代码如下。

import cocos
import pyglet
class Fish(cocos.sprite.Sprite):def __init__(self):textures=[]for i in range(1,11):name_i="0"+str(i) if i<10 else str(i)fish_name_i="textures/fish04_"+name_i+".png"texture=pyglet.resource.image(fish_name_i)textures.append(texture)animation=pyglet.image.Animation.from_image_sequence(textures,0.1)super(Fish, self).__init__(animation)self.position = 800,200self.swim()def swim(self):self.position=800,200self.do(cocos.actions.MoveTo((-20,200),8)+ cocos.actions.CallFunc(self.swim))def on_enter(self):super(Fish, self).on_enter()cocos.director.director.window.push_handlers(self.on_mouse_press)def on_mouse_press(self,x,y,button,modifier):if x > self.x - self.width * 1 / 2 and x < self.x + self.width * 1 / 2 and y > self.y - self.height * 1 / 2 and y < self.y + self.height * 1 / 2:self.explode()def explode(self):self.stop()self.kill()

上述代码运行后,只有点击的位置在鱼精灵的身上时,才会出现鱼精灵的消失。

五、大批鱼类精灵的游动

前面完成了一个鱼类精灵的游动后,鼠标点击到其身上以后,该鱼类精灵就消失了。现在我们产生若干条鱼类,并且产生的位置在纵轴上是随机的。这样鱼类在背景类进行实例化和添加时,需要调用循环结构添加多个鱼类,这些添加的鱼类将其鱼的样式变成多种多样的话,把其中鱼的种类的索引值传入,根据不同的索引值调用不同的鱼类。在鱼类的初始化函数中对纵轴的坐标进行随机,并赋值给鱼类的position位置属性。代码如下。

import cocos
import pyglet
import random
class Fish(cocos.sprite.Sprite):def __init__(self,index):index = "0" + str(index) if index < 10 else str(index)textures=[]for i in range(1,11):name_i="0"+str(i) if i<10 else str(i)fish_name_i="textures/fish"+index+"_"+name_i+".png"texture=pyglet.resource.image(fish_name_i)textures.append(texture)animation=pyglet.image.Animation.from_image_sequence(textures,0.1)super(Fish, self).__init__(animation)self.y=random.randint(10,480)self.position = 800,self.yself.swim()def swim(self):self.y=random.randint(10,480)self.position=800,self.yminutes=random.randint(2,8)self.do(cocos.actions.MoveTo((-20,self.y),minutes)+ cocos.actions.CallFunc(self.swim))def on_enter(self):super(Fish, self).on_enter()cocos.director.director.window.push_handlers(self.on_mouse_press)def on_mouse_press(self,x,y,button,modifier):if x > self.x - self.width * 1 / 2 and x < self.x + self.width * 1 / 2 and y > self.y - self.height * 1 / 2 and y < self.y + self.height * 1 / 2:self.explode()def explode(self):self.stop()self.kill()class Background(cocos.layer.Layer):def __init__(self):super(Background,self).__init__()self.width,self.height=cocos.director.director.get_window_size()sprite=cocos.sprite.Sprite("textures/bg.jpg")sprite.position=self.width//2,self.height//2self.add(sprite)for i in range(2,11):fish=Fish(i)self.add(fish)
if __name__=="__main__":cocos.director.director.init(width=800,height=480);background=Background();main_scene=cocos.scene.Scene(background)cocos.director.director.run(main_scene)

程序中在Fish鱼精灵类方法中首先判断传入的index鱼的种类值是两位数还是一位数,如果是1位数,前面加上0变成为两位数,如果是两位数就正常输出index值。同时修改了文件名的组合方式,”fish”后面跟上传入的index值再跟下划线,后面就是各种鱼的游动状态图。产生鱼类坐标是使用语句random.randint(10,480),也就是在纵坐标的10-480之间产生鱼精灵在图中的竖向位置,将其值赋值给self.y,在重复调用游动方法的swim方法中也要随机产生鱼精灵在图中的竖向位置赋值self.y,再把鱼精灵的初始位置赋值给self.position,并随机产生鱼精灵从屏幕右端游向屏幕左端的时间,这个时间做为MoveTo方法的周期。完成这些代码的调整后,在背景类中循环产生鱼的种类,循环的值从2到11其目的是资源库中是从第2种鱼到第10种鱼。

代码运行后的结果如下图所示。

代码的github地址:https://github.com/wawacode/cocos2dfishgame

这篇关于Python实战案例:Python使用cocos2d实现捕鱼达人的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/808131

相关文章

Python中的魔术方法__new__详解

《Python中的魔术方法__new__详解》:本文主要介绍Python中的魔术方法__new__的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、核心意义与机制1.1 构造过程原理1.2 与 __init__ 对比二、核心功能解析2.1 核心能力2.2

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3

Python Transformer 库安装配置及使用方法

《PythonTransformer库安装配置及使用方法》HuggingFaceTransformers是自然语言处理(NLP)领域最流行的开源库之一,支持基于Transformer架构的预训练模... 目录python 中的 Transformer 库及使用方法一、库的概述二、安装与配置三、基础使用:Pi

Python 中的 with open文件操作的最佳实践

《Python中的withopen文件操作的最佳实践》在Python中,withopen()提供了一个简洁而安全的方式来处理文件操作,它不仅能确保文件在操作完成后自动关闭,还能处理文件操作中的异... 目录什么是 with open()?为什么使用 with open()?使用 with open() 进行

关于pandas的read_csv方法使用解读

《关于pandas的read_csv方法使用解读》:本文主要介绍关于pandas的read_csv方法使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录pandas的read_csv方法解读read_csv中的参数基本参数通用解析参数空值处理相关参数时间处理相关

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

SpringBoot条件注解核心作用与使用场景详解

《SpringBoot条件注解核心作用与使用场景详解》SpringBoot的条件注解为开发者提供了强大的动态配置能力,理解其原理和适用场景是构建灵活、可扩展应用的关键,本文将系统梳理所有常用的条件注... 目录引言一、条件注解的核心机制二、SpringBoot内置条件注解详解1、@ConditionalOn

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(