猫史档案馆


【Python作品分享】游来游去的鱼第二阶段,添加了射击和碰撞检测功能

用户:菜鸟程序员菜鸟程序员查看:0 回复:5 评论:0 创建时间:2019-11-09T12:47:35


【作品展示】

center_image

 

【作品介绍】

pygame实现捕鱼达人第二阶段【射击+碰撞检测】。pygame可以参考43-48思路。增加了射击和碰撞检测功能。【键盘数字1-4可以切换子弹】这里射击算法比较复杂,代码里写了详细注释。

功能还不够完善,只是实现了基本的框架,记录积分、击杀金币特效、击杀音乐和子弹射击特效等等喜欢的喵喵们可以一起研究,欢迎在评论区留言。

https://pan.喵/s/18lAPyX8rZfLBRH4vNIVdog 提取码: 2喵7

场景素材保存在网盘,需要的喵喵们可以下载。下载后保持编译文件和素材文件在同路径就可以了。

【本作品由CJW老年喵工作室出品】

 

【作品源代码】

import pygame
import random
import sys
import math
from PIL import Image
from io import StringIO, BytesIO

#鱼类
class Fish():
    def __init__(self):
        self.w = 1080
        self.h = 600
        self.x = random.randint(-2000, -500)+100  # 鱼X坐标
        self.y = random.randint(0, random.randint(0, 0.7*self.h)+20)  # 鱼Y坐标
        self.speed = random.randint(4, 6)  # 鱼的速度

    def draw(self, image):
        window.blit(image, (self.x, self.y))
        self.updata()

    def updata(self):
        #如果鱼没超出消失范围
        if self.x < self.w:
            #鱼移动
            self.x += self.speed
        else:
            #超出范围回到初始位置
            self.__init__()

#子弹类
class Bullet():
    def __init__(self):
        self.w = 1080
        self.h = 600
        self.x = 560  # 子弹X坐标
        self.y = 600  # 子弹Y坐标
        self.PointX = 0
        self.PointY = 0
        self.speed = random.randint(20, 30)  # 子弹的速度
        self.angle = 0  #子弹旋转角度
        self.stop = True  #子弹停下来
    def draw(self, image,pointX,pointY,roteangle):
        #self.angle = roteangle
        angleImg = pygame.transform.rotate(image, roteangle)
        window.blit(angleImg, (self.x, self.y))
        #如果分母不等于0
        if self.y-pointY != 0 and self.x-pointX != 0:
            self.updata(self.speed*((self.x-pointX) /
                                    (self.y-pointY)), self.speed)
        else:
            #如果分母等于0,设定x速度为0.1
            self.updata(self.speed*((self.x-pointX) /
                                    0.1), self.speed)

    def updata(self,xspeed,yspeed):
        #如果子弹超出消失范围
        if self.y > -30 or self.x > -30 or self.x < 1080:
            #检测子弹是否在运动
            if self.stop == False:
                #子弹移动
                self.x -= xspeed
                self.y -= yspeed         

#获取角度
def getAngle( x1,  y1,  x2,  y2):
        angle = 0.0
        dx = x2 - x1
        dy = y2 - y1
        if x2 == x1:
            angle = math.pi / 2.0
            if y2 == y1:
                angle = 0.0
            elif y2 < y1:
                angle = 3.0 * math.pi / 2.0
        elif x2 > x1 and y2 > y1:
            angle = math.atan(dx / dy)
        elif x2 > x1 and y2 < y1:
            angle = math.pi / 2 + math.atan(-dy / dx)
        elif x2 < x1 and y2 < y1:
            angle = math.pi + math.atan(dx / dy)
        elif x2 < x1 and y2 > y1:
            angle = 3.0 * math.pi / 2.0 + math.atan(dy / -dx)
        return (angle * 180 / math.pi)

#创建鱼
def createFish(imgpath):
    #实例化对象
    fish = Fish()
    fish.__init__()
    fish.draw(cropimg(imgpath, (0, 0, 50, 50)))
    return fish

#创建子弹
def createBullet(img):
    #实例化对象
    bullet = Bullet()
    bullet.__init__()
    bullet.draw(img,0,0,0)
    return bullet

#设置鱼的数量和种类
def SetFish(num, imgpath):
    fishs = []
    for i in range(num):
        fishs.append(createFish(imgpath))
    return fishs

#子弹弹夹
def Setbullet(num, imgpath):
    bullets = []
    for i in range(num):
        bullets.append(createBullet(imgpath))
    return bullets

#切割图片   鱼的图片是一张大图,切割成小图显示
def cropimg(image, region):
    img = Image.open(image)
    cropImg = img.crop(region)
    imgBuf = BytesIO(cropImg.tobytes())
    imgx = pygame.image.frombuffer(
        imgBuf.getvalue(), (region[2] - region[0], region[3] - region[1]), "RGBA")
    return imgx
#######################################start初始化变量start##############################
#图片动画切换
cnt = 0
#鼠标坐标
m_pointX = 0
m_pointY = 0
btRoteAngle = 0
btStart = False
#旋转角度
cannonAngle = 0
#旋转后的图片对象
cannonRote = ""
#######################################end初始化变量end##################################
#素材种类
ImageList = []
#鱼的种类
fishList = []
#弹夹管理
bulletList = []
#鱼图片路径  如果需要添加鱼的素材在imgagePathList中添加,但是最后两个位置鲨鱼要保持固定
#后面通过遍历字典切割图片,鲨鱼的素材需要切割12次,小鱼的素材需要切割8次
imagePathList = {'fish1':'fish1.png', 'fish2':'fish2.png', 'fish3':'fish3.png', 'fish4':'fish4.png', 'fish5':'fish5.png','shark1':'shark1.png', 'shark2':'shark2.png'}
#创建游戏窗口
pygame.init()
window = pygame.display.set_mode([1080, 600])
#----------------游戏资源加载Start-------------------------
#场景图
background = pygame.image.load("bg.png")
#控制台
bottom = pygame.image.load("bottom.png")
#大炮
cannon = pygame.image.load("cannon.png")
#获取图片大小
cannonRect = cannon.get_rect()
cannonRect = cannonRect.move(560,530)
#----------------游戏资源加载End-------------------------
#帧数
timeClock = pygame.time.Clock()

#切割鱼的图片并存储列表,用于动画切换
def cropFish(imagepath,num):
    imageList = []
    #鱼的图片切割
    image = Image.open(imagepath)
    #切割图片从1开始,到n+1结束
    for i in range(1,num+1):
        imageList.append(cropimg(
            imagepath, (0, (i-1)*image.size[1]//num, image.size[0], i*image.size[1]//num)))
    return imageList

for key in imagePathList.values():
    if key == 'shark1.png' or key == 'shark2.png':
        #切割图片
        ImageList.append(cropFish(key, 12))
        #创建鱼类 鲨鱼1条
        fishList.append(SetFish(1, key))
    else:
        #切割图片
        ImageList.append(cropFish(key, 8))
        #创建鱼类  小鱼10条
        fishList.append(SetFish(10, key))
        
#创建子弹
bulletimg = pygame.image.load("fishnet.png")
#创建子弹,预先设置20发,用完了在创建
bulletList = Setbullet(10, bulletimg)
bulletNum = 0
#核心代码
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            pressed_array = pygame.mouse.get_pressed()
            for index in range(len(pressed_array)):
                if pressed_array[index]:
                    #鼠标左键点击
                    if index == 0:
                        #将大炮的转向角度给子弹
                        bulletList[bulletNum].stop = False
                        bulletList[bulletNum].PointX = m_pointX
                        bulletList[bulletNum].PointY = m_pointY
                        bulletList[bulletNum].angle = cannonAngle
                        #每次点击弹夹发射子弹+1
                        bulletNum += 1
                        if bulletNum > 9:
                            bulletNum = 0
                    elif index == 1:
                        #滚轮点击
                        pass
                    elif index == 2:
                        #右键点击
                        pass
        if event.type == pygame.MOUSEMOTION:
            m_pointX, m_pointY = pygame.mouse.get_pos()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_1:
            #切换子弹1
            bulletimg = pygame.image.load("bullet.png")
        if event.type == pygame.KEYDOWN and event.key == pygame.K_2:
            #切换子弹2
            bulletimg = pygame.image.load("paodan.png")
        if event.type == pygame.KEYDOWN and event.key == pygame.K_3:
            #切换子弹3
            bulletimg = pygame.image.load("sandia.png")
    #加载资源
    window.blit(background, (0, 0))
    window.blit(bottom, (170, 530))
    #计算大炮和鼠标位置的角度
    cannonAngle = getAngle(m_pointX, m_pointY, 560, 530)
    #旋转图片
    cannonRote = pygame.transform.rotate(cannon, cannonAngle)
    #校正大炮中心点
    window.blit(cannonRote, cannonRote.get_rect(center=cannonRect.center))
    #加载各种鱼
    for i in range(len(fishList)):
        for j in range(len(fishList[i])):
            for k in range(len(bulletList)):
                #碰撞检测
                if bulletList[k].x - fishList[i][j].x <10 and bulletList[k].y -  fishList[i][j].y < 10:
                    #鱼初始化到起点,子弹初始化到起点,子弹停止运动
                    fishList[i][j].__init__()
                    bulletList[k].__init__()
                    bulletList[k].stop = True
            if i < len(fishList)-2:
                fishList[i][j].draw(ImageList[i][cnt % 4])
            else:
                fishList[i][j].draw(ImageList[i][cnt % 8])
    #遍历弹夹,有多少子弹发喵
    for k in range(len(bulletList)):
        if bulletList[k].y < -30 or bulletList[k].x < -30 or bulletList[k].x > 1110:
            #btStart = False
            bulletList[k].__init__()
            bulletList[k].stop = True 
        #if btStart == True:
        bulletList[k].draw(bulletimg, bulletList[k].PointX,bulletList[k].PointY, bulletList[k].angle)
        
    pygame.display.update()
    #帧数
    timeClock.tick(15)
    cnt += 1

 

【提示】

部分含有Python第三方库相关内容的作品,在海龟编辑器网页端无法运行哦!如遇到这种情况,可以打开下面的链接,下载海龟编辑器客户端:

https://python.codemao.cn


回复

上一页1 页 / 共 1下一页
菜鸟程序员菜鸟程序员

如果你喜欢,甚至可以来点西瓜和炸弹~,直接替换素材图片就可以了

 

 

 

center_image

点赞0


评论


哆啦D猫哆啦D猫

点赞0


评论


葡萄吐司葡萄吐司

棒棒棒emotion_编程猫_点赞emotion_编程猫_点赞emotion_编程猫_点赞

点赞0


评论


QBZ_QBZ_

emotion_编程猫_点赞emotion_编程猫_点赞emotion_编程猫_点赞

点赞0


评论


Frances_RuiFrances_Rui

emotion_编程猫_点赞

点赞0


评论