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按照24个实用大方向精选的上千种工具库汇总整理

《Python按照24个实用大方向精选的上千种工具库汇总整理》本文整理了Python生态中近千个库,涵盖数据处理、图像处理、网络开发、Web框架、人工智能、科学计算、GUI工具、测试框架、环境管理等多... 目录1、数据处理文本处理特殊文本处理html/XML 解析文件处理配置文件处理文档相关日志管理日期和

Python标准库datetime模块日期和时间数据类型解读

《Python标准库datetime模块日期和时间数据类型解读》文章介绍Python中datetime模块的date、time、datetime类,用于处理日期、时间及日期时间结合体,通过属性获取时间... 目录Datetime常用类日期date类型使用时间 time 类型使用日期和时间的结合体–日期时间(

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

Python yield与yield from的简单使用方式

《Pythonyield与yieldfrom的简单使用方式》生成器通过yield定义,可在处理I/O时暂停执行并返回部分结果,待其他任务完成后继续,yieldfrom用于将一个生成器的值传递给另一... 目录python yield与yield from的使用代码结构总结Python yield与yield

Go语言使用select监听多个channel的示例详解

《Go语言使用select监听多个channel的示例详解》本文将聚焦Go并发中的一个强力工具,select,这篇文章将通过实际案例学习如何优雅地监听多个Channel,实现多任务处理、超时控制和非阻... 目录一、前言:为什么要使用select二、实战目标三、案例代码:监听两个任务结果和超时四、运行示例五

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

精选20个好玩又实用的的Python实战项目(有图文代码)

《精选20个好玩又实用的的Python实战项目(有图文代码)》文章介绍了20个实用Python项目,涵盖游戏开发、工具应用、图像处理、机器学习等,使用Tkinter、PIL、OpenCV、Kivy等库... 目录① 猜字游戏② 闹钟③ 骰子模拟器④ 二维码⑤ 语言检测⑥ 加密和解密⑦ URL缩短⑧ 音乐播放