python 全解坦克大战 辅助类 附完整代码【雏形】

我正在博客之星评选,欢迎投票给我 会从投票人中抽奖机械键盘+书,中了会私聊地址

投票连接是:https://bbs.csdn.net/topics/603955346
投票连接是:https://bbs.csdn.net/topics/603955346
投票连接是:https://bbs.csdn.net/topics/603955346
非常感谢给个五星好评(拉到页面最下面就可以打分了)

底部有完整代码想试验的可以去看一下。
然后推一下我一篇文章《外国人最喜欢吃的中国美食是酱油?python数据分析》
想要素材看评论区

突然来的兴趣

这个坦克大战是基于 pygame 的,由于没有完整的学过 pygame,之前一直以为 pygame 对于长按键不支持监听,就在几天前我竟然发现了可以,然后就打开了我的世界大门。

由于这个辅助类我随便写了几个小时,还有很多问题,咱们先慢慢来,先做个坦克大战好了。

这是演示效果:

目前这辅助类的功能有

使用这个辅助类只需要配置信息,自己创建对应对象,主角只需要创建后就可以自动可以移动,敌人也可以自己随机“AI”进行移动,并且子弹自动触碰敌人和墙壁会互相“销毁”完成射击效果。
我们先来看如何使用这辅助类。

使用示例 坦克大战

首先创建一个地图:

map_srpirte=[['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','w','w','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','w','w','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],]

用个list就是可以了,w就是障碍物,简单吧?
接下来设置地图配置:

mapConf={'space':'-','w':"./tank/scene/brick.png",'height':12,'weight':20
}

space表示空间,w表示障碍物的精灵图,宽高为精灵图大小。
接下来写下宽高内容:

screenW=mapConf['weight']*34
screenH=mapConf['height']*48

接下来创建组,设置屏幕:

pygame.init()
screen = pygame.display.set_mode((screenW,screenH))
group_wallt = pygame.sprite.Group()
pygame.key.set_repeat(10)
framerate = pygame.time.Clock()
group_hero = pygame.sprite.Group()
enemy_hero = pygame.sprite.Group()

接下来使用我们的自己写的辅助类 ESprite:

sprite_hero = ESprite(screen,group_hero)

接着设置图片与设置组:

sprite_hero.load("./tank/playerTank/tank_T1_2.png",48, 48, 4, 2)
up="./tank/bullet/bullet_up.png"
down="./tank/bullet/bullet_down.png"
left="./tank/bullet/bullet_left.png"
right="./tank/bullet/bullet_right.png"
group_hero.add(sprite_hero)

使用我们自己写的敌人类循环创建敌人:

enemy_list=[]
for v in range(0,20):enemy = Enemy(screen,enemy_hero)enemy.load("./tank/enemyTank/enemy_1_0.png",48, 48, 4, 2)enemy_hero.add(enemy)enemy_list.append(enemy)

接下来使用自己写的精灵类创建不可触碰体,并且把这个对象添加到主角、敌人不可触碰体设置之中:

posx,posy=0,0
wallet=[]
for rows in map_srpirte:for v in rows:posx+=24if v!=mapConf['space']:sprite_wallt = ESprite(screen,group_wallt)sprite_wallt.load(mapConf['w'],24, 24, 1, 1,posx,posy)group_wallt.add(sprite_wallt)sprite_hero.setCollision(sprite_wallt)#添加不可触碰enemy.setCollision(sprite_wallt)#添加不可触碰print(str(posx)+','+str(posy))posy+=24posx=0

最后开启主循环进行监听、刷新即可:

#主循环
while True:print((screenW,screenH))framerate.tick(30)ticks = pygame.time.get_ticks()for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()exit()elif event.type==pygame.KEYDOWN:print('key down ......')sprite_hero.control.moveControl(event)pos={'up_x':18,'up_y':-10,'down_x':18,'down_y':50,'left_x':-6,'left_y':16,'right_x':50,'right_y':18,}sprite_hero.shoot(up,down,left,right,12,12,1,1,pos,ticks,enemy_list)screen.fill((0,0,100))group_hero.update(ticks)group_hero.draw(screen)enemy_hero.update(ticks)enemy_hero.draw(screen)group_wallt.update(ticks)group_wallt.draw(screen)for v in enemy_list:v.autoMove((screenW,screenH))pygame.display.update()

一、写个精灵类

1.1 初始化

首先创建一个python 文件名为 Etank.py,并在如下引入依赖:

import pygame,random
from pygame.locals import *

pygame 、 random 是所需库,pygame.locals import * 主要是用来找到KEY。

接下来创建一个类名为 ESprite 继承于pygame 的Sprite 基类:

class ESprite(pygame.sprite.Sprite):

在 ESprite 中给到一个 init 方法:

def __init__(self,screen,group=None):

其中 screen 是需要进行屏幕刷新的屏幕对象,group 是当前类实例化后所对应的组。

接下来在 init 中调用父类初始化:

pygame.sprite.Sprite.__init__(self)

接下来在 init 方法中初始化一些内容:

def __init__(self,screen,group=None):#target是屏幕pygame.sprite.Sprite.__init__(self)#self.target_surface = target#精灵渲染目标为屏幕self.screen=screenself.image = None#初始化图片Noneself.main_image = None#主图片self.rect = None#需要画图的区域self.rframe = 0 #图片序列号 行self.cframe = 0 #图片序列号 列self.old_frame = -1#老图片序列号self.frame_width = 1#图片宽self.frame_height = 1#图片高self.cols = 1 #列self.rows = 1 #行self.last_time = 0 #上次更换时的总帧数,用于判断更换帧self.X=0self.Y=0self.speedX=1self.speedY=1self.control=SpriteController(self)#控制初始化self.group=groupself.shootobj=[]self.upImg,self.downImg,self.leftImg,self.rightImg=None,None,None,Noneself.collisions=[]self.enemy_list=[]

这些初始化后的该类属性之后将会在方法中用到,咱们用到时再做说明。

1.2 添加不可碰撞体

在游戏中有很多的不可碰撞体,例如墙壁、障碍物、这些内容对于可活动的游戏觉得是有障碍的,在这里设置一个方法为当前的精灵设置一个不可碰撞体:

#添加不可触碰体
def setCollision(self,collision):self.collisions.append(collision)

1.3加载主图方法

在2d游戏中,每一个98%的角色都是需要图片给予对象视觉呈现,此时写一个方法 load 用于加载当前主图内容:

#加载用
def load(self, filename, width, height,rows,cols,posx=100,posy=100):self.main_image = pygame.image.load(filename).convert_alpha()#加载主图self.frame_width = width#宽高记录self.frame_height = heightself.rect = [posx,posy,width,height]#绘制self.cols = colsself.rows = rows

该方法的参数说明如下:

  • filename 图片路径
  • width 每个图片宽
  • height 每个图片高
  • rows 行
  • cols 列
  • posx 主图起始绘制位置x
  • posy 主图起始绘制位置y

在以上方法中,通过 filename 加载主图,通过宽高选择主图所绘制的区域,图片示例如下:
在这里插入图片描述
宽高指的是图片大小的宽高,posx 和 posy 指图片左上角形成的坐标轴的位置,例如图片大小是4848,总长度是宽 482 长是 48*8,那就是8行2列内容,那么 8 就是 rows 2就是参数 cols,posx 和 posy 就是左上角0和0。

1.5刷新方法

加载图片后还需要刷新内容,创建一个方法 update,接收两个参数,一个是 current_time 是当前帧数,rate 为刷新时的帧值。

#每次图片动态更新绘制区域 动画播放
def update(self, current_time, rate=60):#当前帧总数如果已经超过了最初的 last_time + 60,那么表示#已经超过了60帧,那么 frame 图片序列号+1,开始下一张图片if current_time > self.last_time + rate:self.rframe += 1 #图片序列号+1  if self.rframe>self.cols-1:#大于图片最大列就说明进行了一个循环,因为 self.frame 初始值是 0self.rframe=0self.last_time = current_time#每次更改图片时就记录更换后的帧if self.rframe != self.old_frame:#新老次序不一 表示更换frame#frame_x绘制矩形的位置x就等于图片数*每个宽度得到x坐标值frame_x=self.rframe * self.frame_widthframe_y=self.cframe * self.frame_height#y值跟随上下左右按键切换图,图片规定同一行一个动作# 不同按键对应上下左右# 绘制的区域使用 frame_width frame_height 代替rect = ( frame_x, frame_y, self.frame_width, self.frame_height )self.image = self.main_image.subsurface(rect)#选择区域进行图片提取self.old_frame = self.rframe

以上代码中 if current_time > self.last_time + rate: 表示当前帧是否大于最后一次更换帧数+60,大于则需要刷新,那么则 self.rframe += 1 图片序列号+1 ,表示更换图片 ,但是不能大于本身图片序列的行和列 if self.rframe>self.cols-1,大于则将 self.rframe=0 。

接着就替换一下 self.last_time = current_time 为最后一次的更换帧数,接下来则替换显示图片的坐标值,也就是 rect 值:

if self.rframe != self.old_frame:#新老次序不一 表示更换frame#frame_x绘制矩形的位置x就等于图片数*每个宽度得到x坐标值frame_x=self.rframe * self.frame_widthframe_y=self.cframe * self.frame_height#y值跟随上下左右按键切换图,图片规定同一行一个动作# 不同按键对应上下左右# 绘制的区域使用 frame_width frame_height 代替rect = ( frame_x, frame_y, self.frame_width, self.frame_height )self.image = self.main_image.subsurface(rect)#选择区域进行图片提取self.old_frame = self.rframe

1.6 #创建发射对象

子弹上下左右的主图不一样,朝向不一,如图所示:

此时编写一个方法 shoot:

def shoot(self,upImg,downImg,leftImg,rightImg,width,height,rows,cols,pos,ticks=None,enemy_list=[]):self.enemy_list=enemy_listif self.control.isShoot==True:#创建发射物shootobj=ESprite(self.screen)self.group.add(shootobj)posx,posy=0,0sprite_img=''if self.control.shoot_direction==self.control.direction_UP:posx=self.rect[0]+pos['up_x']posy=self.rect[1]+pos['up_y']sprite_img=upImgelif self.control.shoot_direction==self.control.direction_DOWN:posx=self.rect[0]+pos['down_x']posy=self.rect[1]+pos['down_y']sprite_img=downImgelif self.control.shoot_direction==self.control.direction_LEFT:posx=self.rect[0]+pos['left_x']posy=self.rect[1]+pos['left_y']sprite_img=leftImgelif self.control.shoot_direction==self.control.direction_RIGHT:posx=self.rect[0]+pos['right_x']posy=self.rect[1]+pos['right_y']sprite_img=rightImgshootobj.load(sprite_img, width, height, rows, cols,posx=posx,posy=posy)self.shootobj.append({'obj':shootobj,'shoot_direction':self.control.shoot_direction})          print('SHOOT!!!!!!!!!!...')#print(self.shootobj.rect)print(len(self.shootobj))#加组后一定要刷新,不然会读不到 surface.image 也就是没有在页面之上self.group.update(ticks)self.group.draw(self.screen)#数组中已经创建的继续移动for s in self.shootobj:if s['obj']!=None:SPEEDX=self.control.shoot_SPEEDXSPEEDY=self.control.shoot_SPEEDYif s['shoot_direction']==self.control.direction_UP:print('direction_UP...')SPEEDX=0SPEEDY=-SPEEDYelif s['shoot_direction']==self.control.direction_DOWN:print('direction_DOWN...')SPEEDX=0SPEEDY=+SPEEDYelif s['shoot_direction']==self.control.direction_LEFT:print('direction_LEFT...')SPEEDX=-SPEEDXSPEEDY=0elif s['shoot_direction']==self.control.direction_RIGHT:print('direction_RIGHT...')SPEEDX=SPEEDXSPEEDY=0s['obj'].rect=s['obj'].rect[0]+SPEEDX,s['obj'].rect[1]+SPEEDY,s['obj'].frame_width,s['obj'].frame_heightif self.collisions!=[]:for index, v in enumerate(self.collisions):if s['obj']!=None:if pygame.sprite.collide_mask(s['obj'],v):s['obj'].rect=-1000,-1000,s['obj'].frame_width,s['obj'].frame_heights['obj'].kill()self.collisions[index].rect=-1000,-1000,self.collisions[index].rect[2],self.collisions[index].rect[3]self.collisions[index].kill()#s['obj']=False#s['obj']=Noneif self.enemy_list!=[]:for index, v in enumerate(self.enemy_list):if s['obj']!=None:if pygame.sprite.collide_mask(s['obj'],v):s['obj'].rect=-1000,-1000,s['obj'].frame_width,s['obj'].frame_heights['obj'].kill()self.enemy_list[index].rect=-1000,-1000,self.enemy_list[index].rect[2],self.enemy_list[index].rect[3]self.enemy_list[index].kill()

以上方法中参数 upImg,downImg,leftImg,rightImg 为上下左右子弹的图片,width,height,rows,cols,pos,ticks=None,enemy_list=[] 一次是宽高,行列和ticks 刷新帧,enemy_list 敌人。

因为之后还需要检测敌人碰撞后销毁。

在该函数中第一行打码是 self.enemy_list=enemy_list 表示设置当前的敌人列表。
接着 if self.control.isShoot==True: 这个判断表示是否按发射键(之后会在控制中进行讲解);
按下发射键后就开始创建发射对象,同样这个对象是ESprite 对象:

#创建发射物
shootobj=ESprite(self.screen)
self.group.add(shootobj)
posx,posy=0,0
sprite_img=''

接下来判断此时朝向,(根据之后会有一个控制方法,检测朝向)不同朝向的方位创建不同朝向的子弹:

if self.control.shoot_direction==self.control.direction_UP:posx=self.rect[0]+pos['up_x']posy=self.rect[1]+pos['up_y']sprite_img=upImg
elif self.control.shoot_direction==self.control.direction_DOWN:posx=self.rect[0]+pos['down_x']posy=self.rect[1]+pos['down_y']sprite_img=downImg
elif self.control.shoot_direction==self.control.direction_LEFT:posx=self.rect[0]+pos['left_x']posy=self.rect[1]+pos['left_y']sprite_img=leftImg
elif self.control.shoot_direction==self.control.direction_RIGHT:posx=self.rect[0]+pos['right_x']posy=self.rect[1]+pos['right_y']sprite_img=rightImg

接着加载图片,并且记录方向,如果不记录方向,之后使用同一个方法时将会与自身按键操作重合,会意外的控制子弹前进路线:

shootobj.load(sprite_img, width, height, rows, cols,posx=posx,posy=posy)
self.shootobj.append({'obj':shootobj,'shoot_direction':self.control.shoot_direction})  

接下来开始检测碰撞,检测碰撞前需要在屏幕刷新当前的sprite,因为检测膨胀是需要判断该精灵是否在屏幕之上:

self.group.update(ticks)
self.group.draw(self.screen)

加下来创建一个循环:

#数组中已经创建的继续移动
for s in self.shootobj:if s['obj']!=None:

这个循环遍历子弹是否与某些物体发生碰撞,并且进行位置移动。首先编写位置移动的内容:

SPEEDX=self.control.shoot_SPEEDX
SPEEDY=self.control.shoot_SPEEDY
if s['shoot_direction']==self.control.direction_UP:print('direction_UP...')SPEEDX=0SPEEDY=-SPEEDY
elif s['shoot_direction']==self.control.direction_DOWN:print('direction_DOWN...')SPEEDX=0SPEEDY=+SPEEDY
elif s['shoot_direction']==self.control.direction_LEFT:print('direction_LEFT...')SPEEDX=-SPEEDXSPEEDY=0
elif s['shoot_direction']==self.control.direction_RIGHT:print('direction_RIGHT...')SPEEDX=SPEEDXSPEEDY=0
s['obj'].rect=s['obj'].rect[0]+SPEEDX,s['obj'].rect[1]+SPEEDY,s['obj'].frame_width,s['obj'].frame_height

判断刚刚所记录的方向,给予不同位置移动的坐标。
接着判断是否发生碰撞:

if self.collisions!=[]:for index, v in enumerate(self.collisions):if s['obj']!=None:if pygame.sprite.collide_mask(s['obj'],v):s['obj'].rect=-1000,-1000,s['obj'].frame_width,s['obj'].frame_heights['obj'].kill()self.collisions[index].rect=-1000,-1000,self.collisions[index].rect[2],self.collisions[index].rect[3]self.collisions[index].kill()

只要设置了 collisions 阻碍物,那么就遍历阻碍物是否与子弹发生碰撞,如果发生膨胀首先将该物体移动到屏幕之外调用 kill() 方法对其进行销毁。这样就实现了子弹设计到物体,物体和子弹都同时消失。

最后判断子弹和敌人是否发生碰撞,遍历敌人:

if self.enemy_list!=[]:
for index, v in enumerate(self.enemy_list):if s['obj']!=None:if pygame.sprite.collide_mask(s['obj'],v):s['obj'].rect=-1000,-1000,s['obj'].frame_width,s['obj'].frame_heights['obj'].kill()self.enemy_list[index].rect=-1000,-1000,self.enemy_list[index].rect[2],self.enemy_list[index].rect[3]self.enemy_list[index].kill()

实现方法与墙体类似。
最后在遍历之外加一个设计关闭即可,因为按一次就发射一个子弹:

self.control.isShoot=False#创建完一个后又关闭

二、写个精灵控制类

首先创建一个精灵控制类和初始化方法:

#精灵控制类            
class SpriteController():def __init__(self,sprite): self.sprite=spriteself.direction=Noneself.shoot_direction=1self.direction_UP=1self.direction_DOWN=2self.direction_LEFT=3self.direction_RIGHT=4self.shoot_SPEEDX=10self.shoot_SPEEDY=10self.isShoot=False

接着编写精灵控制响应的方法:

#移动控制
def moveControl(self,event):stepX=self.sprite.speedXstepY=self.sprite.speedY#if self.isShoot!=True:if event.key == pygame.K_RIGHT:stepY=0stepX=stepXself.sprite.cframe=3self.shoot_direction=4elif event.key == pygame.K_LEFT:stepX=-stepXstepY=0self.sprite.cframe=2self.shoot_direction=3elif event.key == pygame.K_UP:stepY=-stepYstepX=0self.sprite.cframe=0self.shoot_direction=1elif event.key == pygame.K_DOWN:stepY=stepYstepX=0self.sprite.cframe=1self.shoot_direction=2elif event.key == pygame.K_SPACE:self.isShoot=True stepX,stepY=0,0 self.sprite.rect=self.sprite.rect[0]+stepX,self.sprite.rect[1]+stepY,self.sprite.frame_width,self.sprite.frame_heightif self.sprite.collisions!=[]:for v in self.sprite.collisions:result = pygame.sprite.collide_mask(self.sprite,v)while result:#bug 墙壁反弹错位unstepX,unstepY=stepX,stepYif unstepX!=0:if unstepX>0:unstepX=+10else:unstepX=-10if unstepY!=0:if unstepY>0:unstepY=+10else:unstepY=-10result = pygame.sprite.collide_mask(self.sprite,v)#for vi in range(0,20):self.sprite.rect=self.sprite.rect[0]-stepX,self.sprite.rect[1]-stepY,self.sprite.frame_width,self.sprite.frame_heightprint ("Collision occurred")

moveControl 方法接收1个参数event,判断按下键的内容,根据不同按键响应不同的移动参数,其他内容都是基础内容,主要是对于阻碍物的阻碍效果:

if self.sprite.collisions!=[]:for v in self.sprite.collisions:result = pygame.sprite.collide_mask(self.sprite,v)while result:#bug 墙壁反弹错位unstepX,unstepY=stepX,stepYif unstepX!=0:if unstepX>0:unstepX=+10else:unstepX=-10if unstepY!=0:if unstepY>0:unstepY=+10else:unstepY=-10result = pygame.sprite.collide_mask(self.sprite,v)#for vi in range(0,20):self.sprite.rect=self.sprite.rect[0]-stepX,self.sprite.rect[1]-stepY,self.sprite.frame_width,self.sprite.frame_heightprint ("Collision occurred")

遍历后如果发生碰撞直接给予回退:

self.sprite.rect=self.sprite.rect[0]-stepX,self.sprite.rect[1]-stepY,self.sprite.frame_width,self.sprite.frame_height

三、敌人AI类

敌人类属于 ESprite 类,首先创建一个类及初始化方法:

#敌人
class Enemy(ESprite):def __init__(self, screen, group=None):super().__init__(screen, group=group)self.screen=screenself.group=group#self.AIControl=SpriteController()self.movieStep=0self.stepY,self.stepX=0,10

movieStep 为默认自动运行次数,self.stepY,self.stepX=0,10 为默认行走值。

接下来编写自动运行方法:

def autoMove(self,Size):self.group.update(ticks)self.group.draw(self.screen)if self.movieStep==0:random.seed(random.randint(0,100))d=random.randint(1,16)if d>0 and d<5:#上self.stepY=-10self.stepX=0elif d>4 and d<9:#下self.stepY=10self.stepX=0elif d>8 and d<13:#左self.stepX=-10self.stepY=0elif d>12 and d<17:#右self.stepX=10self.stepY=0self.movieStep=20if self.movieStep!=0:if (self.rect[0],self.rect[1])>(60,60) and (self.rect[0],self.rect[1]) < (Size[0]-60,Size[1]-60):self.rect=self.rect[0]+self.stepX,self.rect[1]+self.stepY,self.frame_width,self.frame_heightself.movieStep-=1if self.collisions!=[]:for v in self.collisions:#self.group.update(ticks)#self.group.draw(self.screen)result = pygame.sprite.collide_mask(self,v)while result:#bug 墙壁反弹错位unstepX,unstepY=self.stepX,self.stepYif unstepX!=0:if unstepX>0:unstepX=+10else:unstepX=-10if unstepY!=0:if unstepY>0:unstepY=+10else:unstepY=-10result = pygame.sprite.collide_mask(self,v)#for vi in range(0,20):self.rect=self.rect[0]-self.stepX,self.rect[1]-self.stepY,self.frame_width,self.frame_heightprint ("Collision occurred")

以上代码中以下代码表示该AI随机上下左右:

if self.movieStep==0:random.seed(random.randint(0,100))d=random.randint(1,16)if d>0 and d<5:#上self.stepY=-10self.stepX=0elif d>4 and d<9:#下self.stepY=10self.stepX=0elif d>8 and d<13:#左self.stepX=-10self.stepY=0elif d>12 and d<17:#右self.stepX=10self.stepY=0self.movieStep=20
if self.movieStep!=0:if (self.rect[0],self.rect[1])>(60,60) and (self.rect[0],self.rect[1]) < (Size[0]-60,Size[1]-60):self.rect=self.rect[0]+self.stepX,self.rect[1]+self.stepY,self.frame_width,self.frame_heightself.movieStep-=1

不同方向他有不同值对应,self.movieStep运行次数为0则重新置于20,若不等于0则自动运行,只需要设置对应的 rect 即可。

接着就是判断是否碰到障碍物,实现与控制方法一致:

if self.collisions!=[]:for v in self.collisions:#self.group.update(ticks)#self.group.draw(self.screen)result = pygame.sprite.collide_mask(self,v)while result:#bug 墙壁反弹错位unstepX,unstepY=self.stepX,self.stepYif unstepX!=0:if unstepX>0:unstepX=+10else:unstepX=-10if unstepY!=0:if unstepY>0:unstepY=+10else:unstepY=-10result = pygame.sprite.collide_mask(self,v)#for vi in range(0,20):self.rect=self.rect[0]-self.stepX,self.rect[1]-self.stepY,self.frame_width,self.frame_heightprint ("Collision occurred")

完整代码

import pygame,random
from pygame.locals import *class MySprite(pygame.sprite.Sprite):def __init__(self,screen,group=None):#target是屏幕pygame.sprite.Sprite.__init__(self)#self.target_surface = target#精灵渲染目标为屏幕self.screen=screenself.image = None#初始化图片Noneself.main_image = None#主图片self.rect = None#需要画图的区域self.rframe = 0 #图片序列号 行self.cframe = 0 #图片序列号 列self.old_frame = -1#老图片序列号self.frame_width = 1#图片宽self.frame_height = 1#图片高self.cols = 1 #列self.rows = 1 #行self.last_time = 0 #上次更换时的总帧数,用于判断更换帧self.X=0self.Y=0self.speedX=1self.speedY=1self.control=SpriteController(self)#控制初始化self.group=groupself.shootobj=[]self.upImg,self.downImg,self.leftImg,self.rightImg=None,None,None,Noneself.collisions=[]self.enemy_list=[]#添加不可触碰体def setCollision(self,collision):self.collisions.append(collision)#加载用def load(self, filename, width, height,rows,cols,posx=100,posy=100):self.main_image = pygame.image.load(filename).convert_alpha()#加载主图self.frame_width = width#宽高记录self.frame_height = heightself.rect = [posx,posy,width,height]#绘制self.cols = colsself.rows = rows#每次图片动态更新绘制区域 动画播放def update(self, current_time, rate=60):#当前帧总数如果已经超过了最初的 last_time + 60,那么表示#已经超过了60帧,那么 frame 图片序列号+1,开始下一张图片if current_time > self.last_time + rate:self.rframe += 1 #图片序列号+1  if self.rframe>self.cols-1:#大于图片最大列就说明进行了一个循环,因为 self.frame 初始值是 0self.rframe=0self.last_time = current_time#每次更改图片时就记录更换后的帧if self.rframe != self.old_frame:#新老次序不一 表示更换frame#frame_x绘制矩形的位置x就等于图片数*每个宽度得到x坐标值frame_x=self.rframe * self.frame_widthframe_y=self.cframe * self.frame_height#y值跟随上下左右按键切换图,图片规定同一行一个动作# 不同按键对应上下左右# 绘制的区域使用 frame_width frame_height 代替rect = ( frame_x, frame_y, self.frame_width, self.frame_height )self.image = self.main_image.subsurface(rect)#选择区域进行图片提取self.old_frame = self.rframe#设置上下左右发射对象def setShootSprite(self,up,down,left,right,width,height,rows,cols):self.upImg=upself.downImg=downself.leftImg=leftself.rightImg=rightself.swidth=widthself.sheight=heightself.srows=rowsself.scols=cols#创建发射对象def shoot(self,upImg,downImg,leftImg,rightImg,width,height,rows,cols,pos,ticks=None,enemy_list=[]):self.enemy_list=enemy_listif self.control.isShoot==True:#创建发射物shootobj=MySprite(self.screen)self.group.add(shootobj)posx,posy=0,0sprite_img=''if self.control.shoot_direction==self.control.direction_UP:posx=self.rect[0]+pos['up_x']posy=self.rect[1]+pos['up_y']sprite_img=upImgelif self.control.shoot_direction==self.control.direction_DOWN:posx=self.rect[0]+pos['down_x']posy=self.rect[1]+pos['down_y']sprite_img=downImgelif self.control.shoot_direction==self.control.direction_LEFT:posx=self.rect[0]+pos['left_x']posy=self.rect[1]+pos['left_y']sprite_img=leftImgelif self.control.shoot_direction==self.control.direction_RIGHT:posx=self.rect[0]+pos['right_x']posy=self.rect[1]+pos['right_y']sprite_img=rightImgshootobj.load(sprite_img, width, height, rows, cols,posx=posx,posy=posy)self.shootobj.append({'obj':shootobj,'shoot_direction':self.control.shoot_direction})          print('SHOOT!!!!!!!!!!...')#print(self.shootobj.rect)print(len(self.shootobj))#加组后一定要刷新,不然会读不到 surface.image 也就是没有在页面之上self.group.update(ticks)self.group.draw(self.screen)#数组中已经创建的继续移动for s in self.shootobj:if s['obj']!=None:SPEEDX=self.control.shoot_SPEEDXSPEEDY=self.control.shoot_SPEEDYif s['shoot_direction']==self.control.direction_UP:print('direction_UP...')SPEEDX=0SPEEDY=-SPEEDYelif s['shoot_direction']==self.control.direction_DOWN:print('direction_DOWN...')SPEEDX=0SPEEDY=+SPEEDYelif s['shoot_direction']==self.control.direction_LEFT:print('direction_LEFT...')SPEEDX=-SPEEDXSPEEDY=0elif s['shoot_direction']==self.control.direction_RIGHT:print('direction_RIGHT...')SPEEDX=SPEEDXSPEEDY=0s['obj'].rect=s['obj'].rect[0]+SPEEDX,s['obj'].rect[1]+SPEEDY,s['obj'].frame_width,s['obj'].frame_heightif self.collisions!=[]:for index, v in enumerate(self.collisions):if s['obj']!=None:if pygame.sprite.collide_mask(s['obj'],v):s['obj'].rect=-1000,-1000,s['obj'].frame_width,s['obj'].frame_heights['obj'].kill()self.collisions[index].rect=-1000,-1000,self.collisions[index].rect[2],self.collisions[index].rect[3]self.collisions[index].kill()#s['obj']=False#s['obj']=Noneif self.enemy_list!=[]:for index, v in enumerate(self.enemy_list):if s['obj']!=None:if pygame.sprite.collide_mask(s['obj'],v):s['obj'].rect=-1000,-1000,s['obj'].frame_width,s['obj'].frame_heights['obj'].kill()self.enemy_list[index].rect=-1000,-1000,self.enemy_list[index].rect[2],self.enemy_list[index].rect[3]self.enemy_list[index].kill()self.control.isShoot=False#创建完一个后又关闭#精灵控制类            
class SpriteController():def __init__(self,sprite): self.sprite=spriteself.direction=Noneself.shoot_direction=1self.direction_UP=1self.direction_DOWN=2self.direction_LEFT=3self.direction_RIGHT=4self.shoot_SPEEDX=10self.shoot_SPEEDY=10self.isShoot=False#移动控制def moveControl(self,event):stepX=self.sprite.speedXstepY=self.sprite.speedY#if self.isShoot!=True:if event.key == pygame.K_RIGHT:stepY=0stepX=stepXself.sprite.cframe=3self.shoot_direction=4elif event.key == pygame.K_LEFT:stepX=-stepXstepY=0self.sprite.cframe=2self.shoot_direction=3elif event.key == pygame.K_UP:stepY=-stepYstepX=0self.sprite.cframe=0self.shoot_direction=1elif event.key == pygame.K_DOWN:stepY=stepYstepX=0self.sprite.cframe=1self.shoot_direction=2elif event.key == pygame.K_SPACE:self.isShoot=True stepX,stepY=0,0 self.sprite.rect=self.sprite.rect[0]+stepX,self.sprite.rect[1]+stepY,self.sprite.frame_width,self.sprite.frame_heightif self.sprite.collisions!=[]:for v in self.sprite.collisions:result = pygame.sprite.collide_mask(self.sprite,v)while result:#bug 墙壁反弹错位unstepX,unstepY=stepX,stepYif unstepX!=0:if unstepX>0:unstepX=+10else:unstepX=-10if unstepY!=0:if unstepY>0:unstepY=+10else:unstepY=-10result = pygame.sprite.collide_mask(self.sprite,v)#for vi in range(0,20):self.sprite.rect=self.sprite.rect[0]-stepX,self.sprite.rect[1]-stepY,self.sprite.frame_width,self.sprite.frame_heightprint ("Collision occurred")#敌人
class Enemy(MySprite):def __init__(self, screen, group=None):super().__init__(screen, group=group)self.screen=screenself.group=group#self.AIControl=SpriteController()self.movieStep=0self.stepY,self.stepX=0,10def autoMove(self,Size):self.group.update(ticks)self.group.draw(self.screen)if self.movieStep==0:random.seed(random.randint(0,100))d=random.randint(1,16)if d>0 and d<5:#上self.stepY=-10self.stepX=0elif d>4 and d<9:#下self.stepY=10self.stepX=0elif d>8 and d<13:#左self.stepX=-10self.stepY=0elif d>12 and d<17:#右self.stepX=10self.stepY=0self.movieStep=20if self.movieStep!=0:if (self.rect[0],self.rect[1])>(60,60) and (self.rect[0],self.rect[1]) < (Size[0]-60,Size[1]-60):self.rect=self.rect[0]+self.stepX,self.rect[1]+self.stepY,self.frame_width,self.frame_heightself.movieStep-=1if self.collisions!=[]:for v in self.collisions:#self.group.update(ticks)#self.group.draw(self.screen)result = pygame.sprite.collide_mask(self,v)while result:#bug 墙壁反弹错位unstepX,unstepY=self.stepX,self.stepYif unstepX!=0:if unstepX>0:unstepX=+10else:unstepX=-10if unstepY!=0:if unstepY>0:unstepY=+10else:unstepY=-10result = pygame.sprite.collide_mask(self,v)#for vi in range(0,20):self.rect=self.rect[0]-self.stepX,self.rect[1]-self.stepY,self.frame_width,self.frame_heightprint ("Collision occurred")map_srpirte=[['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','w','w','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','w','w','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','w','w','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],['-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-'],]
mapConf={'space':'-','w':"./tank/scene/brick.png",'height':12,'weight':20
}
#map_srpirteConf={['w',24,24,1,1]}
screenW=mapConf['weight']*34
screenH=mapConf['height']*48pygame.init()
screen = pygame.display.set_mode((screenW,screenH))
group_wallt = pygame.sprite.Group()
pygame.key.set_repeat(10)
framerate = pygame.time.Clock()group_hero = pygame.sprite.Group()
enemy_hero = pygame.sprite.Group()
sprite_hero = MySprite(screen,group_hero)sprite_hero.load("./tank/playerTank/tank_T1_2.png",48, 48, 4, 2)
up="./tank/bullet/bullet_up.png"
down="./tank/bullet/bullet_down.png"
left="./tank/bullet/bullet_left.png"
right="./tank/bullet/bullet_right.png"
#sprite_hero.setShootSprite()
group_hero.add(sprite_hero)enemy_list=[]
for v in range(0,20):enemy = Enemy(screen,enemy_hero)enemy.load("./tank/enemyTank/enemy_1_0.png",48, 48, 4, 2)enemy_hero.add(enemy)enemy_list.append(enemy)posx,posy=0,0
wallet=[]
for rows in map_srpirte:for v in rows:posx+=24if v!=mapConf['space']:sprite_wallt = MySprite(screen,group_wallt)sprite_wallt.load(mapConf['w'],24, 24, 1, 1,posx,posy)group_wallt.add(sprite_wallt)sprite_hero.setCollision(sprite_wallt)enemy.setCollision(sprite_wallt)print(str(posx)+','+str(posy))posy+=24posx=0#sprite_wallt = MySprite(screen,group_wallt)
#sprite_wallt.load(mapConf['w'],24, 24, 1, 1,posx,posy)
#group_wallt.add(sprite_wallt)
#主循环
while True:print((screenW,screenH))framerate.tick(30)ticks = pygame.time.get_ticks()for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()exit()elif event.type==pygame.KEYDOWN:print('key down ......')sprite_hero.control.moveControl(event)pos={'up_x':18,'up_y':-10,'down_x':18,'down_y':50,'left_x':-6,'left_y':16,'right_x':50,'right_y':18,}sprite_hero.shoot(up,down,left,right,12,12,1,1,pos,ticks,enemy_list)screen.fill((0,0,100))group_hero.update(ticks)group_hero.draw(screen)enemy_hero.update(ticks)enemy_hero.draw(screen)group_wallt.update(ticks)group_wallt.draw(screen)for v in enemy_list:v.autoMove((screenW,screenH))pygame.display.update()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/286632.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vc++ mfc中拖动效果的实现 借助于CImageList

拖动是界面编程频繁使用的一个效果&#xff0c;在windows系统下可谓大行其道。纵观时下的应用软件几乎各个都支持各种各样拖动的效果&#xff0c;windows7更是把拖动做到了极致。其实说起来拖动的实现也很简单&#xff0c;对于有句柄的对象都可以通过MoveWindow或SetWindowPos实…

有序的Map集合--LinkedHashMap

提出问题&#xff1a; 在写一个dao的时候&#xff0c;我的需求是这个dao是一个万能的&#xff0c;目前的方法只有一个查询出实体类对应的表中所有的数据&#xff0c;通过传入的对象&#xff0c;利用反射获取实体类中的属性名&#xff0c;属性类型&#xff0c;利用字符串拼接获取…

yii 前后台分离及登陆验证

2019独角兽企业重金招聘Python工程师标准>>> 比较合理的做法其实是分成两个框架来布署&#xff1b;然而这样说法也太绝对。 事实上是针对不同系统&#xff0c;应采用不同的方法。如为CMS系统&#xff0c;则不需很复杂的权限管理&#xff0c;但如果有管理员与会员之分…

Kibana

2019独角兽企业重金招聘Python工程师标准>>> Kibana是一个基于浏览器页面的Elasticsearch前端展示工具。Kibana全部使用HTML语言和Javascript编写的&#xff0c;查询语法是基于Lucene的查询语法。允许布尔运算符、通配符和字段筛选。注意关键字要大写 全文搜索 在搜…

电脑QQ能登上,网页打不开的解决办法

打开360卫士&#xff0c;在功能大全里选择网络优化&#xff0c;断网急救箱。 可以看到DNS服务异常、浏览器配置异常&#xff0c;点击立即修复。

个人黑名单 抄袭耻辱墙

抄袭耻辱墙 博主抄袭文原文我爱Python数据挖掘https://blog.csdn.net/weixin_38037405/article/details/125862095https://blog.csdn.net/A757291228/article/details/117464313黄埔数据分析https://blog.csdn.net/weixin_39060517/article/details/118024847https://blog.csdn…

快速掌握 ASP.NET 身份认证框架 Identity(一)

推荐关注「码侠江湖」加星标&#xff0c;时刻不忘江湖事ASP.NET Core 内置了一个强大的身份认证框架 Identity&#xff0c;掌握它可以让我们快速开发高安全的身份认证功能&#xff0c;不仅如此&#xff0c;它还是一个基于数据库的用户管理系统&#xff0c;其中包含了大量的辅助…

浅谈大型web系统架构

动态应用&#xff0c;是相对于网站静态内容而言&#xff0c;是指以c/c、php、Java、perl、.net等服务器端语言开发的网络应用软件&#xff0c;比如论坛、网络相册、交友、BLOG等常见应用。动态应用系统通常与数据库系统、缓存系统、分布式存储系统等密不可分。   大型动态应用…

PHP: 手把手编写自己的 MVC 框架实例教程

1 什么是MVC MVC模式&#xff08;Model-View-Controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;把软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&#xff09;。 …

2021年复盘总结发现了C站博主缺少的赚钱之路

一、 我2021年的六大Flag 其实最开始我是不打算年终总结的&#xff0c;因为2021年我的十大Flag都没有完成&#xff0c;我说出来可能你会嘲笑我&#xff0c;所以我打算还是说出来吧。 这六大Flag如下&#xff1a; C站百万粉百篇实战文其他自媒体平台十万粉公众号一万粉财务自…

五大微信小程序开发IDE深度评测

微信小程序已经内测有一段时间了&#xff0c;笔者本着好奇加学习的心态写了几个小demo&#xff0c;虽然在MINA框架上并没有遇到太多的坑&#xff0c;但官方开发工具实在不敢恭维。 api提示不全&#xff0c;要一个个查api啊&#xff0c;写代码超级慢啊 很多必备的快捷键都没有&…

Maui的学习之路(2)--Mac窗体设置

Maui的学习之路今天是我开启Maui学习之路的第二天&#xff0c;我不是很高兴又能水一篇文章&#xff0c;我只能说这文章真好水。话不多说&#xff0c;我们进入正题&#xff0c;昨天解决了Windows下TitleBar以及窗体大小的问题&#xff0c;今天同样的问题&#xff0c;在Mac上又要…

ArcGIS10.8中如何获取线状、面状数据的折点,并计算折点坐标?

如下图所示为面状要素,ArcGIS10.8中如何获取线状和面状数据的折点(起点、终点、中点、端点),并计算折点的坐标(X,Y,Z,M)? 下图所示为线状(Polyline)和面状(Polygon)要素的起点、终点和折点的示意图。

[转]Cordova + Ionic in Visual Studio - 101 Tutorial [Part I]

本文转自&#xff1a;http://binarylies.ghost.io/cordova-ionic-in-visual-studio/ Hi everyone, I thought about lending a hand to all the people that are, as I have been recently, exploring Cordova and all its features for the first time. For the ones still tr…

【转】学会这13个原则写UI界面文案,用户才能秒懂

原文网址&#xff1a;http://www.niaogebiji.com/article-12011-1.html 摘要: 首先&#xff0c;在写UI文案之前&#xff0c;为了理清思路&#xff0c;要先搞清楚三个问题&#xff1a;我&#xff08;设计师&#xff09;想让用户做什么&#xff1f; – 我写文案的目的为什么要让用…

【前端就业课 第一阶段】HTML5 零基础到实战(一)基础代码结构详解

注意&#xff1a;手机&#xff08;APP&#xff09;打开&#xff0c;内容显示更佳&#xff0c;不会的私聊博主即可 想要拿代码或加入学习计划&#xff08;** 博主会监督你并且教你写文章 **&#xff09;的拉到最下面&#xff08;PC端Web打开&#xff09;加博主即可&#xff0c;目…

【框架篇】mvc、mvp、mvvm使用关系总结

MVC MVC全名是Model View Controller&#xff0c;是模型(model)&#xff0d;视图(view)&#xff0d;控制器(controller)的缩写&#xff0c;一种软件设计典范&#xff0c;用一种业务逻辑、数据、界面显示分离的方法组织代码&#xff0c;将业务逻辑聚集到一个部件里面&#xff0c…

Android之使用自定义华为扫描SDK扫描二维码和识别本地图片

1、需求 更具UI的设计实现扫描二维码和识别本地图片二维码功能。 zxing扫描二维码还可以,但是识别本地图片二维码功能效果太差,非常不理想,看了看多github很多zxing扩展的开源项目,识别本地图片二维码功能效果不乐观,有些甚至还有裁剪本地图片,还是不能识别,果断放弃zb…

Matlab R2016b简体中文版安装教程(附Matlab R2016b百度网盘下载地址)

下载的Matlab R2016b软件安装包(文末附有下载地址)目录如下所示: 安装过程: 1. 安装主程序R2016b_win64_dvd1.iso和R2016b_win64_dvd2.iso 由于目前大多数及其都是Win8或10系统,所以选中R2016b_win64_dvd1.iso,右键→Windows资源管理器打开。Win7系统可以安装好压软件之后…

深度学习String、StringBuffer、StringBuilder

相信String这个类是Java中使用得最频繁的类之一&#xff0c;并且又是各大公司面试喜欢问到的地方&#xff0c;今天就来和大家一起学习一下String、StringBuilder和StringBuffer这几个类&#xff0c;分析它们的异同点以及了解各个类适用的场景。下面是本文的目录大纲&#xff1a…