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

相关文章

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

Golang使用minio替代文件系统的实战教程

《Golang使用minio替代文件系统的实战教程》本文讨论项目开发中直接文件系统的限制或不足,接着介绍Minio对象存储的优势,同时给出Golang的实际示例代码,包括初始化客户端、读取minio对... 目录文件系统 vs Minio文件系统不足:对象存储:miniogolang连接Minio配置Min

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python pyinstaller实现图形化打包工具

《Pythonpyinstaller实现图形化打包工具》:本文主要介绍一个使用PythonPYQT5制作的关于pyinstaller打包工具,代替传统的cmd黑窗口模式打包页面,实现更快捷方便的... 目录1.简介2.运行效果3.相关源码1.简介一个使用python PYQT5制作的关于pyinstall

使用Python实现大文件切片上传及断点续传的方法

《使用Python实现大文件切片上传及断点续传的方法》本文介绍了使用Python实现大文件切片上传及断点续传的方法,包括功能模块划分(获取上传文件接口状态、临时文件夹状态信息、切片上传、切片合并)、整... 目录概要整体架构流程技术细节获取上传文件状态接口获取临时文件夹状态信息接口切片上传功能文件合并功能小

Golang使用etcd构建分布式锁的示例分享

《Golang使用etcd构建分布式锁的示例分享》在本教程中,我们将学习如何使用Go和etcd构建分布式锁系统,分布式锁系统对于管理对分布式系统中共享资源的并发访问至关重要,它有助于维护一致性,防止竞... 目录引言环境准备新建Go项目实现加锁和解锁功能测试分布式锁重构实现失败重试总结引言我们将使用Go作

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

C#实现文件读写到SQLite数据库

《C#实现文件读写到SQLite数据库》这篇文章主要为大家详细介绍了使用C#将文件读写到SQLite数据库的几种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录1. 使用 BLOB 存储文件2. 存储文件路径3. 分块存储文件《文件读写到SQLite数据库China编程的方法》博客中,介绍了文

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

JAVA利用顺序表实现“杨辉三角”的思路及代码示例

《JAVA利用顺序表实现“杨辉三角”的思路及代码示例》杨辉三角形是中国古代数学的杰出研究成果之一,是我国北宋数学家贾宪于1050年首先发现并使用的,:本文主要介绍JAVA利用顺序表实现杨辉三角的思... 目录一:“杨辉三角”题目链接二:题解代码:三:题解思路:总结一:“杨辉三角”题目链接题目链接:点击这里