3 Star 12 Fork 4

youlinghei/python版坦克大战

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
Tank.py 22.07 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
import sys
import pygame
import pygame.freetype
import random
import time
from resource import *
from stagemap import *
from tools import *
pygame.init()
screen = pygame.display.set_mode(size)
pygame.display.set_caption("坦克大战")
fclock = pygame.time.Clock()
BLACK = 0, 0, 0
WHITE = 255, 255, 255
GREY = 125, 125, 125
start_sound = pygame.mixer.Sound('sound/start.wav')
start_sound.set_volume(0.5)
home_blast_sound = pygame.mixer.Sound('sound/blast.wav')
home_blast_sound.set_volume(0.5)
hit_sound = pygame.mixer.Sound('sound/hit.wav')
hit_sound.set_volume(0.5)
get_tank = pygame.mixer.Sound('sound/GetBonus.wav')
get_tank.set_volume(0.5)
# 坦克爆炸音效
bang_sound = pygame.mixer.Sound('sound/bang.wav')
bang_sound.set_volume(0.1)
font = pygame.freetype.Font('Fonts/PressStart2P-Regular.ttf', 20)
stage = 0
stage_pass = False
# 创建玩家的老家
home_group = pygame.sprite.Group()
home = Home()
home_group.add(home)
home_reinforce = False
# 创建玩家的坦克精灵
player_group = pygame.sprite.Group()
player1 = PlayerTank(1)
player2 = PlayerTank(2)
player2.rect.centerx = wall_size * 17
player2.rect.bottom = height
title_image = pygame.image.load('images/others/title.png')
title_rect = title_image.get_rect()
title_rect.centerx = (width + wall_size * 4) / 2
title_rect.top = height
game_over_image = pygame.image.load('images/others/gameover.png')
game_over_rect = game_over_image.get_rect()
game_over_rect.centerx = width / 2
game_over_rect.top = height
selecttank_image = pygame.image.load('images/others/selecttank.png')
selecttank_rect = selecttank_image.get_rect()
select = 1
selecttank_rect.right = 270
selecttank_rect.y = 262
# 敌方坦克精灵组
enemy_group = pygame.sprite.Group()
ENEMY_EVENT = pygame.USEREVENT
pygame.time.set_timer(ENEMY_EVENT, 3000)
ENEMY_FIRE_EVENT = pygame.USEREVENT + 1
pygame.time.set_timer(ENEMY_FIRE_EVENT, 1500)
# 每一关总共有20辆敌方坦克
enemy_num = 20
born_position = [(wall_size, wall_size), (wall_size * 13, wall_size), (wall_size * 25, wall_size)]
born_index = 1
enemy_index = 0
food_group = pygame.sprite.Group()
clock_start = 0
clock_end = 0
enemy_pause = False
destroy_group = pygame.sprite.Group()
def show_stage():
screen.fill(GREY)
stage_text, stage_rect = font.render('STAGE %d' % stage, fgcolor=BLACK, size=20)
stage_rect.centerx = (width + wall_size * 4) / 2
stage_rect.centery = height / 2
screen.blit(stage_text, stage_rect)
pygame.display.update()
pygame.time.delay(2000)
def next_stage():
"""过关,进入下一关"""
global stage
global start
global enemy_num
global stage_pass
global born_index
global enemy_index
global enemy_pause
stage += 1
if stage <= len(all_map):
enemy_num = 20
born_index = 1
enemy_index = 0
stage_pass = False
enemy_pause = False
food_group.empty()
map_init(stage)
start_sound.play()
show_stage()
for p in player_group:
p.reset()
else:
stage_pass = False
stage = 0
for p in player_group:
p.level = 0
p.life = 3
p.upgrade()
p.reset()
player_group.empty()
title_rect.centerx = (width + wall_size * 4) / 2
title_rect.top = height
start = False
def menu():
"""选择模式菜单"""
global select
global start
global stage
screen.fill(BLACK)
screen.blit(title_image, title_rect)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_f:
if title_rect.y == 0:
if select < 2:
select += 1
elif select >= 2:
select = 1
else:
title_rect.y = 0
elif event.key == pygame.K_h:
if title_rect.y == 0:
if select == 1:
player_group.add(player1)
elif select == 2:
player_group.add(player1, player2)
next_stage()
start = True
else:
title_rect.y = 0
# 选择菜单从下往上飞入
if title_rect.y > 0:
title_rect.y -= 180 / fps
else:
selecttank_rect.y = 232 + select * 32
screen.blit(selecttank_image, selecttank_rect)
def key_event():
global enemy_num
global born_index
global pause
global enemy_index
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN and home.active:
if event.key == pygame.K_h:
pause = True
if player1.active:
if event.key == pygame.K_j:
player1.fire()
# 坦克转向的时候位置总是控制在墙体宽度的整数倍
if event.key == pygame.K_w:
if player1.rect.x % wall_size:
player1.rect.x = round(player1.rect.x / wall_size) * wall_size
if event.key == pygame.K_s:
if player1.rect.x % wall_size:
player1.rect.x = round(player1.rect.x / wall_size) * wall_size
if event.key == pygame.K_a:
if player1.rect.y % wall_size:
player1.rect.y = round(player1.rect.y / wall_size) * wall_size
if event.key == pygame.K_d:
if player1.rect.y % wall_size:
player1.rect.y = round(player1.rect.y / wall_size) * wall_size
if select == 2 and player2.active:
if event.key == pygame.K_KP1:
player2.fire()
# 坦克转向的时候位置总是控制在墙体宽度的整数倍
if event.key == pygame.K_UP:
if player2.rect.x % wall_size:
player2.rect.x = round(player2.rect.x / wall_size) * wall_size
if event.key == pygame.K_DOWN:
if player2.rect.x % wall_size:
player2.rect.x = round(player2.rect.x / wall_size) * wall_size
if event.key == pygame.K_LEFT:
if player2.rect.y % wall_size:
player2.rect.y = round(player2.rect.y / wall_size) * wall_size
if event.key == pygame.K_RIGHT:
if player2.rect.y % wall_size:
player2.rect.y = round(player2.rect.y / wall_size) * wall_size
if event.type == pygame.KEYUP and home.active:
if event.key == pygame.K_w:
player1.frame = 1
player1.driving_sound.stop()
elif event.key == pygame.K_s:
player1.frame = 1
player1.driving_sound.stop()
elif event.key == pygame.K_a:
player1.frame = 1
player1.driving_sound.stop()
elif event.key == pygame.K_d:
player1.frame = 1
player1.driving_sound.stop()
if event.key == pygame.K_UP:
player2.frame = 1
player2.driving_sound.stop()
elif event.key == pygame.K_DOWN:
player2.frame = 1
player2.driving_sound.stop()
elif event.key == pygame.K_LEFT:
player2.frame = 1
player2.driving_sound.stop()
elif event.key == pygame.K_RIGHT:
player2.frame = 1
player2.driving_sound.stop()
if event.type == ENEMY_EVENT:
if len(enemy_group) < 5 and enemy_num > 0:
enemy = EnemyTank(stage_enemy[stage - 1][enemy_index])
enemy.rect.center = born_position[born_index]
born_index += 1
enemy_index += 1
if born_index == 3:
born_index = 0
enemy_num -= 1
enemy.direction = random.choice(['down', 'left', 'right'])
enemy_group.add(enemy)
elif event.type == ENEMY_FIRE_EVENT:
for e in enemy_group:
if not enemy_pause:
e.fire()
def main():
while True:
screen.fill(GREY)
pygame.draw.rect(screen, BLACK, (0, 0, width, height))
if start:
if pause:
game_pause()
else:
key_event()
check_collide()
update()
else:
menu()
if stage_pass:
next_stage()
pygame.display.update()
fclock.tick(fps)
def check_collide():
"""碰撞检测"""
global select
global start
global gameover
global stage_pass
global clock_start
global clock_end
global enemy_pause
global home_reinforce
for p in player_group:
if p.active and home.active:
p.move()
# 玩家坦克遇到障碍物
hit_home = pygame.sprite.collide_rect(p, home)
hit_wall = pygame.sprite.spritecollide(p, wall_group, False)
if hit_home:
check_hit(p, home)
elif hit_wall:
for w in hit_wall:
if not w.crossover:
check_hit(p, w)
# 吃道具
hit_food = pygame.sprite.spritecollide(p, food_group, False)
if hit_food:
for fd in hit_food:
if fd.food_num == 1:
for e1 in enemy_group:
e1.active = False
fd.kill()
elif fd.food_num == 2:
enemy_pause = True
clock_start = time.time()
fd.kill()
elif fd.food_num == 3:
p.level = 3
p.upgrade()
fd.kill()
elif fd.food_num == 4:
home_reinforce = True
fd.kill()
elif fd.food_num == 5:
p.protected = True
p.protective_cover.time = 0
fd.kill()
elif fd.food_num == 6:
if p.level < 3:
p.level += 1
p.upgrade()
fd.kill()
elif fd.food_num == 7:
p.life += 1
get_tank.play()
fd.kill()
# 子弹碰撞
for b in p.bullets:
if b.active:
b.move()
# 子弹击中障碍物
shoot_wall = pygame.sprite.spritecollide(b, wall_group, False)
if shoot_wall:
for w in shoot_wall:
if w.solid != 0:
if w.solid == 1 or b.level > 2:
b.active = False
w.kill()
elif w.solid > 1:
hit_sound.play()
b.active = False
# 子弹击中老家
shoot_home = pygame.sprite.spritecollide(b, home_group, False)
if shoot_home:
b.active = False
for p2 in player_group:
p2.driving_sound.stop()
home.active = False
explosion = DestroyEffects(home)
destroy_group.add(explosion)
gameover = True
home_blast_sound.play()
pygame.mixer.music.stop()
# break
shoot_enemy = pygame.sprite.spritecollide(b, enemy_group, False)
if shoot_enemy:
b.active = False
for et in shoot_enemy:
et.blood -= 1
if et.blood > 0:
hit_sound.play()
else:
if et.food:
food_num = random.randint(1, 7)
food = Food(food_num)
food_group.add(food)
bang_sound.play()
et.active = False
if enemy_pause:
clock_end = time.time()
if clock_end - clock_start > 12:
enemy_pause = False
for e in enemy_group:
if e.active:
if not enemy_pause:
e.move()
# 敌方坦克遇到障碍物
hit_home = pygame.sprite.collide_rect(e, home)
if hit_home:
check_hit(e, home)
e.reselect_direction()
for w in wall_group:
if pygame.sprite.collide_rect(e, w):
if not w.crossover:
check_hit(e, w)
e.reselect_direction()
break
# 子弹碰撞
for b in e.bullets:
if b.active:
b.move()
# 子弹击中障碍物
shoot_wall = pygame.sprite.spritecollide(b, wall_group, False)
if shoot_wall:
for w in shoot_wall:
if w.solid == 1:
b.active = False
w.kill()
elif w.solid > 1:
hit_sound.play()
b.active = False
# 子弹击中老家
shoot_home = pygame.sprite.spritecollide(b, home_group, False)
if shoot_home and home.active:
b.active = False
for p3 in player_group:
p3.driving_sound.stop()
home.active = False
explosion = DestroyEffects(home)
destroy_group.add(explosion)
gameover = True
home_blast_sound.play()
pygame.mixer.music.stop()
break
# 敌人子弹击中玩家坦克
shoot_player = pygame.sprite.spritecollide(b, player_group, False)
if shoot_player:
for p in shoot_player:
if p.active:
b.active = False
if not p.protected:
p.blood -= 1
if p.blood > 0:
hit_sound.play()
p.level -= 1
p.upgrade()
else:
bang_sound.play()
p.life -= 1
p.active = False
explosion = DestroyEffects(p)
destroy_group.add(explosion)
p.level = 0
p.upgrade()
if p.life > 0:
p.reset()
# break
# 和玩家子弹相互抵消
for p in player_group:
shoot_bullet = pygame.sprite.spritecollide(b, p.bullets, True)
if shoot_bullet:
b.kill()
# 地方坦克相遇后改变方向
for e2 in enemy_group:
if e2 is not e:
if pygame.sprite.collide_rect(e, e2):
check_hit(e, e2)
e.reselect_direction()
if select == 1:
if player1.life == 0:
gameover = True
elif select == 2:
if player1.life == 0 and player2.life == 0:
gameover = True
if len(enemy_group) == 0 and enemy_num == 0:
for p in player_group:
p.driving_sound.stop()
stage_pass = True
def check_hit(object1, object2):
"""
检测遇到障碍物能否穿过
:param object1: 碰撞的精灵
:param object2: 被撞的精灵
:return:
"""
if object1.direction == 'up':
object1.rect.y = object2.rect.bottom
elif object1.direction == 'down':
object1.rect.bottom = object2.rect.y
elif object1.direction == 'left':
object1.rect.x = object2.rect.right
elif object1.direction == 'right':
object1.rect.right = object2.rect.x
def draw_ui():
"""绘制右侧界面的信息"""
global enemy_num
global select
# 生成剩余敌方坦克的二维列表
enemy_list = [[0, 0],
[0, 0],
[0, 0],
[0, 0],
[0, 0],
[0, 0],
[0, 0],
[0, 0],
[0, 0],
[0, 0]
]
image_num = 0
if enemy_num > 0:
for row in range(10):
for col in range(2):
if image_num >= enemy_num:
break
image_num += 1
enemy_list[row][col] = 1
# 根据剩余敌方坦克的列表绘制到屏幕右侧
for i in range(10):
r = enemy_list[i]
for j in range(2):
c = r[j]
if c == 1:
enemy_num_rect.x = width + wall_size * (j + 1)
enemy_num_rect.y = wall_size * (i + 1)
screen.blit(enemy_num_image, enemy_num_rect)
else:
break
if player1.life > 0:
player1_remain = player1.life - 1
else:
player1_remain = 0
player1_num_text, player1_num_rect = font.render('%d' % player1_remain, fgcolor=BLACK, size=16)
player1_num_rect.x = wall_size * 28 - 8
player1_num_rect.y = wall_size * 16
stage_num_image, stage_num_rect = font.render('%d' % stage, fgcolor=BLACK, size=16)
stage_num_rect.x = wall_size * 28 - 8
stage_num_rect.y = wall_size * 22
screen.blit(IP_image, IP_rect)
screen.blit(player_life_image, player1_life_rect)
screen.blit(player1_num_text, player1_num_rect)
screen.blit(flag_image, flag_rect)
screen.blit(stage_num_image, stage_num_rect)
if select == 2:
if player2.life > 0:
player2_remain = player2.life - 1
else:
player2_remain = 0
player2_num_text, player2_num_rect = font.render('%d' % player2_remain, fgcolor=BLACK, size=16)
player2_num_rect.x = wall_size * 28 - 8
player2_num_rect.y = wall_size * 19
screen.blit(IIP_image, IIP_rect)
screen.blit(player_life_image, player2_life_rect)
screen.blit(player2_num_text, player2_num_rect)
def update():
"""更新游戏中所有元素的显示"""
global home_reinforce
# 绘制右侧信息
draw_ui()
# 绘制大本营
if home_reinforce:
reinforce_home()
home_reinforce = False
if home.active:
screen.blit(home.image1, home.rect)
else:
screen.blit(home.image2, home.rect)
# 绘制玩家坦克
for p in player_group:
if p.active:
screen.blit(p.image, p.rect)
if p.protected:
p.protective_cover.draw(p.rect)
p.protected_end = time.time()
if p.protective_cover.time >= 11:
p.protected = False
p.protective_cover.time = 0
# 绘制子弹
for bullet in p.bullets:
if bullet.active:
pygame.draw.rect(screen, WHITE, bullet.rect)
else:
explosion = DestroyEffects(bullet)
destroy_group.add(explosion)
bullet.kill()
# 绘制敌方坦克
for e in enemy_group:
if e.active:
screen.blit(e.image, e.rect)
else:
explosion = DestroyEffects(e)
destroy_group.add(explosion)
e.kill()
# 绘制敌方坦克子弹
for b in e.bullets:
if b.active:
pygame.draw.rect(screen, WHITE, b.rect)
else:
explosion = DestroyEffects(b)
destroy_group.add(explosion)
b.kill()
# 绘制地图
for w in wall_group:
screen.blit(w.image, w.rect)
# 绘制食物
for f in food_group:
screen.blit(f.image, f.rect)
if gameover:
game_over()
# 绘制爆炸效果
for explosion in destroy_group:
explosion.show()
def game_pause():
global pause
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_h:
pause = False
for p in player_group:
if p.active:
screen.blit(p.image, p.rect)
if p.protected:
screen.blit(p.protective_cover.image, p.rect)
for b in p.bullets:
if b.active:
pygame.draw.rect(screen, WHITE, b.rect)
for e in enemy_group:
if e.active:
screen.blit(e.image, e.rect)
for b in e.bullets:
if b.active:
pygame.draw.rect(screen, WHITE, b.rect)
# 绘制地图
for w in wall_group:
screen.blit(w.image, w.rect)
draw_ui()
screen.blit(home.image1, home.rect)
for f in food_group:
screen.blit(f.image, f.rect)
# 绘制爆炸效果
for explosion in destroy_group:
explosion.show()
def game_over():
screen.blit(game_over_image, game_over_rect)
if game_over_rect.centery > height / 2:
game_over_rect.y -= 180 / fps
if __name__ == '__main__':
main()
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/youlinghei/python-tank-battle.git
[email protected]:youlinghei/python-tank-battle.git
youlinghei
python-tank-battle
python版坦克大战
master

搜索帮助