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.pswp.cn/news/286632.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/286632.shtml
英文地址,請注明出處:http://en.pswp.cn/news/286632.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vc++ mfc中拖動效果的實現 借助于CImageList

拖動是界面編程頻繁使用的一個效果&#xff0c;在windows系統下可謂大行其道。縱觀時下的應用軟件幾乎各個都支持各種各樣拖動的效果&#xff0c;windows7更是把拖動做到了極致。其實說起來拖動的實現也很簡單&#xff0c;對于有句柄的對象都可以通過MoveWindow或SetWindowPos實…

從瀏覽器地址欄輸入url到顯示頁面的步驟

從瀏覽器地址欄輸入url到顯示頁面的步驟(以HTTP為例)- 在瀏覽器地址欄輸入URL- 瀏覽器查看緩存&#xff0c;如果請求資源在緩存中并且新鮮&#xff0c;跳轉到轉碼步驟 - 如果資源未緩存&#xff0c;發起新請求 - 如果已緩存&#xff0c;檢驗是否足夠新鮮&#xff0c;足夠…

有序的Map集合--LinkedHashMap

提出問題&#xff1a; 在寫一個dao的時候&#xff0c;我的需求是這個dao是一個萬能的&#xff0c;目前的方法只有一個查詢出實體類對應的表中所有的數據&#xff0c;通過傳入的對象&#xff0c;利用反射獲取實體類中的屬性名&#xff0c;屬性類型&#xff0c;利用字符串拼接獲取…

Leetcode之僅僅反轉字母

1 題目 給定一個字符串 S,返回 “反轉后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置發生反轉。 示例 1:輸入:"ab-cd" 輸出:"dc-ba" 示例 2:輸入:"a-bC-dEf-ghIj" 輸出:"j-Ih-gfE-dCba" 示例 3:輸入:&qu…

【SignalR全套系列】之在.Net Core 中實現長輪詢

微信公眾號&#xff1a;趣編程ACE關注可了解更多的.NET日常實戰開發技巧&#xff0c;如需源碼 請后臺留言 源碼;前文回顧【SignalR全套系列】之在.Net Core 中實現Server-Send Events消息推送【SignalR全套系列】之在.NetCore中實現WebSocket雙工通信【SignalR全套系列】之在.N…

完美解決ArcGIS10.2和Erdas9.2軟件沖突的方法:共存!

用過ArcGIS和Erdas軟件的都知道&#xff0c;二者存在著服務的沖突&#xff0c;為了解決共存的問題&#xff0c;筆者曾多次重裝系統&#xff0c;但未能如愿以償。其實不需要相互關閉服務如此麻煩。那如何在安裝有arcgis的電腦安裝erdas并解決沖突呢&#xff1f;直接上視頻教程。…

架構師之路16年精選50篇

2016精選索引&#xff0c;點擊標題閱讀相關文章。【方法論】《秒殺系統架構優化思路》《分布式ID生成器》《互聯網架構&#xff0c;如何進行容量設計》《線程數究竟設多少合理》《單點系統架構的可用性與性能優化》《關于負載均衡的一切》《異構服務器負載均衡及過載保護》《LV…

yii 前后臺分離及登陸驗證

2019獨角獸企業重金招聘Python工程師標準>>> 比較合理的做法其實是分成兩個框架來布署&#xff1b;然而這樣說法也太絕對。 事實上是針對不同系統&#xff0c;應采用不同的方法。如為CMS系統&#xff0c;則不需很復雜的權限管理&#xff0c;但如果有管理員與會員之分…

雙谷人才財務管理(序)

IT是一個迅速發展的行業&#xff0c;教育是一個良心的行業&#xff0c;兩者交集——IT培訓&#xff0c;在整個市場中占有一個不可或缺的地位。好多大學生&#xff0c;抱怨找不到工作&#xff1b;好多企業找不到合適的程序員&#xff0c;這幾年這個問題越來越嚴重。。。。于是IT…

Android之打開手機系統相冊

1、需求 打開系統相冊&#xff0c;獲取圖片進行掃描操作 2、代碼實現 Intent pickIntent new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");Ca…

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等常見應用。動態應用系統通常與數據庫系統、緩存系統、分布式存儲系統等密不可分。   大型動態應用…

Android之webview長按超鏈接類型獲取鏈接文字及url、長按圖片鏈接類型分別獲取圖片和鏈接的url

1 、需求 webview長按超鏈接獲取鏈接文字及urlwebview長按圖片鏈接類型獲分別獲取圖片和鏈接的url 2、解決辦法 1)、設置webview的OnLongClickListener事件,關鍵代碼如下 companion object {const val LINK_TYPE = 1const val IMAGE_LINK_TYPE = 2}var mHandler = object :…

PostgreSQL 統計信息pg_statistic格式及導入導出dump_stat - 兼容Oracle

標簽 PostgreSQL , dump_stat , 統計信息 , 導出導入 背景 《PostgreSQL 規格評估 - 微觀、宏觀、精準 多視角估算數據庫性能(選型、做預算不求人)》 EXPLAIN是PG數據庫用于輸出SQL執行計劃的語法&#xff0c; 1、生成的執行計劃中包含COST一項。 如果校準了成本因子&#xff0…

PHP: 手把手編寫自己的 MVC 框架實例教程

1 什么是MVC MVC模式&#xff08;Model-View-Controller&#xff09;是軟件工程中的一種軟件架構模式&#xff0c;把軟件系統分為三個基本部分&#xff1a;模型&#xff08;Model&#xff09;、視圖&#xff08;View&#xff09;和控制器&#xff08;Controller&#xff09;。 …

freemarker 異常處理

SSH2處理方案&#xff1a; freemarker文件如果出錯&#xff0c;網站的前臺頁面會報出很明顯的錯誤-焦黃的背景&#xff0c;血紅的文字&#xff0c;很不利于用戶體驗的。如何修改這個問題呢&#xff1f;首先需要在struts.xml配置文件里添加下面一行代碼&#xff1a; 1<consta…

ArcGIS10.8按屬性選擇中根據關鍵字like模糊查詢方法總結

在實際工作中,通常需要按照某一個或某幾個關鍵字進行模糊查詢,已到達快速、準確、高效查詢的目的。在ArcGIS中是通過SQL語句,利用關鍵字like來實現的。例如我們可以借助like快速查詢滿足以某一個關鍵字開頭,以某一個關鍵字結尾,或者包含某一個關鍵字的結果。 在ArcGIS中,…