游戏最基础的东东:精灵动画
贴一段代码吧:
import random
import pygame
from const import *
class Block(pygame.sprite.DirtySprite):
#精灵(赃精灵)
def __init__(self, engine, who, type, pos, delay = 0, layer = LIST_BALKS):
pygame.sprite.DirtySprite.__init__(self)
self.engine = engine
self.mode = 1 #-1销毁 0出生 1正常 2爆炸
self.who = who #-1边界 0可击毁地图目标 1玩家1 2玩家2 3敌人
self.type = type #类型,决定精灵显示样式
self.scale = False #是否缩放(子弹爆炸效果和坦克爆炸效果用的同样的资源,坦克爆炸动画尺寸大一些)
self.dir = DIR_UP #方向(对运动目标有效)
self.can_through = False #是否允许通过
self.can_destory = True #是否允许消灭(子弹可以击毁)
self.destory_fire = 1 #击毁需要火力等级
self.pos = pos #显示位置
self.animation = True #贴图动画(玩家坦克2帧,不动时就不需动画效果了)
self.frame_delay = delay #帧延时(多帧时有效)
self.image_change(self.type, self.frame_delay)
self.engine.add_sprite(self, layer)
def get_rect(self):
pt = [self.pos[0]+1, self.pos[1] + 1]
return pygame.Rect(pt, (self.width-2, self.height-2))
def image_change(self, type = -1, delay = 0):
if type >= 0:
self.type = type
if delay > 0:
self.frame_delay = delay
self.frame_index = 0
angle = DIR_CFG[self.dir]["angle"]
self.frames = self.engine.get_frame(self.type, angle, self.scale)
self.frame_count = len(self.frames)
self.image = self.frames[self.frame_index]
self.width = self.image.get_width()
self.height = self.image.get_height()
def inc_counter(self, timer):
#累计一定时间后进行帧切换
if self.frame_delay > 0 and timer % self.frame_delay == self.frame_delay - 1:
self.next_frmae()
def next_frmae(self):
if self.frame_count > 1:
if self.frame_index + 1 == self.frame_count:
self.frame_index = 0
else:
self.frame_index += 1
if self.animation:
self.image = self.frames[self.frame_index]
def hit(self, bullet):
if self.can_destory and bullet.level >= self.destory_fire:
self.die()
def draw(self, screen):
screen.blit(self.image, self.pos)
def die(self):
self.kill()
del self
里面有个timer,由主程序的Clock.Tick()后进行累加,就是每帧累加一次,每关都从0开始
通过精灵Mode、FrameDelay来确定每帧显示的时间,一般的障碍物像砖头、钢板是没有动画的(只有一帧),河有动画(两帧)
玩家的坦克也有动画,但是不动时是允许显示动画的,所以后面要覆盖inc_counter方法,被击中效果也不一样所以也要覆盖hit、draw、die方法
再上几个障碍子类的代码:
class Brick(Block):
#砖
def __init__(self, engine, who, type, pos, delay, layer):
Block.__init__(self, engine, who, type, pos, delay, layer)
self.can_through = False
def hit(self, bullet):
if bullet.who != WHO_ENEMY:
self.engine.play_sound(SND_BRICK)
if bullet.level > 2:
self.die()
else:
#击中不中位置,火力不同产生的销毁效果也不同
type = BRICK_TAB[bullet.dir][self.type]
if type == M_00:
self.die()
else:
self.image_change(type)
class Ice(Block):
#冰
def __init__(self, engine, who, type, pos, delay, layer):
Block.__init__(self, engine, who, type, pos, delay, layer)
self.can_through = True
self.can_destory = False
class River(Block):
#河
def __init__(self, engine, who, type, pos, delay, layer):
Block.__init__(self, engine, who, type, pos, 30, layer)
self.can_through = False
self.can_destory = False
class Steel(Block):
#钢板
def __init__(self, engine, who, type, pos, delay, layer):
Block.__init__(self, engine, who, type, pos, delay, layer)
self.can_through = False
def hit(self, bullet):
if bullet.level > 2:
self.die()
else:
if bullet.who != WHO_ENEMY:
self.engine.play_sound(SND_STEEL)
class Base(Block):
#基地
def __init__(self, engine, who, type, pos, delay, layer):
Block.__init__(self, engine, who, type, pos, delay, layer)
self.can_through = False
def hit(self, bullet):
self.mode = -1
self.can_through = True
self.can_destory = False
self.next_frmae()
self.animation = False
self.engine.game_over()
self.engine.play_sound(SND_KILL)
class Food(Block):
#宝物
def __init__(self, engine):
if engine.food != None:
engine.food.die()
engine.food = None
foodtype = random.choice([P_STAR, P_CAPS, P_TIMR, P_BOMB, P_LIFE, P_SPAD]) #宝物类型
pos = [32 + random.randint(1, 22) * 16, 32 + random.randint(1, 20) * 16]
Block.__init__(self, engine, WHO_FOOD, foodtype, pos, 10, LIST_COVER)
self.engine.play_sound(SND_SPECIAL)
self.can_through = True
self.duration = FOODS_DURATION
self.effect_time = self.engine.timer
self.engine.food = self
def get_rect(self):
pt = [self.pos[0]+8, self.pos[1] + 8]
return pygame.Rect(pt, (self.width-16, self.height-16))
def eat(self, player):
self.mode = -1
pdict = self.engine.players[player.who]
pdict["Score"] += 500
self.engine.play_sound(SND_ADDLIFE if self.type == P_LIFE else SND_PROPS)
if self.type == P_LIFE:
pdict["Life"] += 1
elif self.type == P_STAR:#等级提升
player.add_fire(1)
elif self.type == P_CAPS:#无敌模式
player.set_god()
elif self.type == P_BOMB:#杀死所有敌坦克列表
self.engine.bomb_enemy()
elif self.type == P_TIMR:#暂时敌人动画也要暂停
self.engine.stop_enemy()
elif self.type == P_SPAD:#加强老窝
self.engine.protect_base()
self.duration = SCORE_DURATION
self.effect_time = self.engine.timer
self.frame_delay = 0
self.image_change(S_500)
def inc_counter(self, timer):
#累计一定时间后进行帧切换
if timer - self.effect_time > self.duration:
self.die()
else:
super().inc_counter(timer)
def die(self):
self.engine.food = None
super().die()