class PowerUp(Sprite): """ Represents a powerup""" def __init__(self, P_TYPE, screen, x, y): """ Init attributes""" super().__init__() # Attributes self.P_TYPE = P_TYPE self.sheet = settings.power_up_sheet self.sheet_cols = settings.power_up_sheet_cols self.sheet_rows = settings.power_up_sheet_rows self.spritesheet = SpriteSheet(self.sheet, self.sheet_cols, self.sheet_rows) self.image = self.spritesheet.get_image(int(self.P_TYPE), colorkey=-1) self.x = x self.y = y self.width = self.image.get_width() self.height = self.image.get_height() self.rect = pygame.Rect(x, y, self.width, self.height) self.screen = screen self.spin_degrees = 1 * settings.power_up_spin_factor def draw(self): """ Draws powerup to screen""" self.spritesheet.draw(self.screen, int(self.P_TYPE), self.rect.x, self.rect.y) def update(self): """ Updates movement of powerup""" self.rect.y += settings.power_up_speed_factor
class Player1(): """Represents main character""" def __init__(self, screen): """Initialize the main character""" # initialize screen attribute self.screen = screen # load spritesheet self.sprite_sheet = SpriteSheet("sprites/rocket_ship4x2.png", 4, 2) self.width = self.sprite_sheet.cellWidth self.height = self.sprite_sheet.cellHeight # initialize player start coordinates self.x = screen.get_rect().width / 2 self.y = screen.get_rect().height / 2 # screen rect self.screen_rect = screen.get_rect() self.screen_width = self.screen_rect.width self.screen_height = self.screen_rect.height # keeps track of the need to move self.moving_right = False self.moving_left = False self.moving_up = False self.moving_down = False def getRect(self): """return a current rect for player object""" return pygame.Rect(self.x - self.width / 2, self.y - self.height / 2, self.width, self.height) def blit(self, handle): """Draws character""" self.sprite_sheet.draw(self.screen, 0, int(self.x), int(self.y), int(handle)) def update(self): """updates player coordinates when moving""" rect = self.getRect() if self.moving_right: if rect.right < self.screen_width: self.x += 1 if self.moving_left: if rect.left > 0: self.x -= 1 if self.moving_up: if rect.top > 0: self.y -= 1 if self.moving_down: if rect.bottom < self.screen_height: self.y += 1
class Explosion(Sprite): """ Represents an explosion and runs explosion animation""" def __init__(self, screen, x, y, indices=()): """ Setting up attributes""" # Call parent constructor super(Explosion, self).__init__() # Screen attribute self.screen = screen # Spritesheet containing explosion animation self.sprite_sheet = SpriteSheet(settings.explosion_sheet, settings.explosion_cols, settings.explosion_rows) # Animation length in milliseconds self.time_length = settings.explosion_anim_length # Animation instance self.animation = Animation(self.sprite_sheet, settings.explosion_anim_length, indices) # Prints animation debug info to terminal. self.animation.debug_mode = False # Is animation finished? self.finished = False # Start with first image in animation list self.image = self.animation.images[0] # Location rect for explosion self.rect = pygame.Rect(x, y, self.image.get_width(), self.image.get_height()) def draw(self): """ Starts and draws explosion """ # Start animation self.animation.run() # Draw explosion if there are frames left if self.animation.current_frame < self.animation.num_frames: self.sprite_sheet.draw(self.screen, self.animation.current_frame - 1, self.rect.x, self.rect.y) def update(self): """ Updates image to draw from animation""" self.image = self.animation.images[self.animation.current_frame - 1] # Update finished flag self.finished = self.animation.anim_finished
class Character(): """Represents main character""" def __init__(self, screen): """Initialize the main character""" self.screen = screen self.image = pygame.image.load('sprites/chronotrigger2.png') self.rect = self.image.get_rect() self.screen_rect = screen.get_rect() self.rect.centerx = self.screen_rect.centerx self.rect.centery = self.screen_rect.centery self.sprite_sheet = SpriteSheet("sprites/chronotrigger2.png", 4, 4) def blit(self, x, y, handle): """Draws character""" self.sprite_sheet.draw(self.screen, 0, int(x), int(y), int(handle))
class Background: def __init__(self,dimensions): self.lastFrameTime = time.time() self.dimensions = dimensions self.clouds = simplegui.load_image("https://raw.githubusercontent.com/CougarTasker/twenty-four/master/proto/images/background_clouds.png") self.sun = simplegui.load_image("https://raw.githubusercontent.com/CougarTasker/twenty-four/master/proto/images/sun.png") self.water_world = simplegui.load_image("https://raw.githubusercontent.com/CougarTasker/twenty-four/master/proto/images/underwater-seamless-landscape-cartoon-background-vector-7524975.png") self.bubbles = SS("https://raw.githubusercontent.com/CougarTasker/twenty-four/master/proto/images/Bubble1.png",(6,5),time=1250,scale=0.22) self.carol = SS("https://raw.githubusercontent.com/CougarTasker/twenty-four/master/proto/images/carol.png",(5,1),time=800,scale=0.22) self.perl = SS("https://raw.githubusercontent.com/CougarTasker/twenty-four/master/proto/images/pearl.png",(3,3),time=3000,scale=0.22,looping=False) #self.floor = simplegui.load_image() def background(self,canvas,pollycount,wavecount,frequency,height,waveheight,color): path = [(0,self.dimensions[1])] offset = self.lastFrameTime%(1/frequency)*frequency for x in range(pollycount+1): ang = x/pollycount*wavecount + offset ang *= 2*math.pi path.append((x/pollycount*self.dimensions[0],((math.sin(ang)*waveheight/2+height)*self.dimensions[1]))) path.append((self.dimensions[0],0)) path.append((0,0)) canvas.draw_polygon(path,1,color,color) def draw_wave_parts(self,canvas,poly,color): for path in poly: if len(path) > 2: canvas.draw_polygon(path,1,color,color) def poly(self,pollycount,wavecount,frequency,height,waveheight): path = [] offset = self.lastFrameTime%(1/frequency)*frequency for x in range(pollycount+1): ang = x/pollycount*wavecount + offset ang *= 2*math.pi path.append((x/pollycount*self.dimensions[0],((math.sin(ang)*waveheight/2+height)*self.dimensions[1]))) return path def sub(self,pollycount,a,b,c): paths = [] drawing = False forward = [] backward = [] for x in range(pollycount+1): if a[x][1] <= b[x][1] and a[x][1] <= c[x][1]: if not drawing: drawing = True forward = [] if x>0: bint = self.intersection(a[x-1],a[x],b[x-1],b[x]) cint = self.intersection(a[x-1],a[x],c[x-1],c[x]) if bint[1] < cint[1]: forward.append(bint) else: forward.append(cint) backward = [] forward.append(a[x]) if b[x][1]<c[x][1]: backward.append(b[x]) else: backward.append(c[x]) else: if drawing: bint = self.intersection(a[x-1],a[x],b[x-1],b[x]) cint = self.intersection(a[x-1],a[x],c[x-1],c[x]) if bint[1] < cint[1]: forward.append(bint) else: forward.append(cint) drawing = False backward.reverse() paths.append(forward+backward) if drawing: drawing = False backward.reverse() paths.append(forward+backward) return paths def intersection(self,a,b,c,d): a = V(a[0],a[1]) b = V(b[0],b[1]) c = V(c[0],c[1]) d = V(d[0],d[1]) cd = d-c ab = b-a u = (a.cross(ab)-c.cross(ab))/cd.cross(ab) l = (c.cross(cd)-a.cross(cd))/ab.cross(cd) if u>=0 and u<= 1 and l >= 0 and l <= 1: return (u * cd + c).get_p() else: return (0,1000) def draw_sun(self,canvas,height): canvas.draw_image(self.sun,(250,250),(500,500),(self.dimensions[0]-self.dimensions[1]*height/2,self.dimensions[1]*height/2),(self.dimensions[1]*height,self.dimensions[1]*height)) def looping_clouds(self,canvas,frequency,height): offset = self.lastFrameTime%(1/frequency)*frequency dim = (2400,300) cen = (1200,150) width = math.floor(dim[0]/dim[1]*height*self.dimensions[1]) canvas.draw_image(self.clouds, cen, dim,(width/2-offset*width,height*self.dimensions[1]/2),(width,height*self.dimensions[1])) canvas.draw_image(self.clouds, cen, dim,(width/2+width-offset*width,height*self.dimensions[1]/2),(width,height*self.dimensions[1])) canvas.draw_image(self.clouds, cen, dim,(width/2+width*2-offset*width,height*self.dimensions[1]/2),(width,height*self.dimensions[1])) def draw_carol(self,canvas,x=0.5): self.carol.draw(canvas,center=(x*self.dimensions[0],self.dimensions[1]-self.carol.adim[1]*self.carol.scale/2)) self.bubbles.draw(canvas,center=(x*self.dimensions[0],self.dimensions[1]-self.bubbles.adim[1]*self.bubbles.scale/2)) def draw_perl(self,canvas,x = 0.5): self.perl.draw(canvas,center=(x*self.dimensions[0],self.dimensions[1]-self.perl.adim[1]*self.perl.scale/2)) def draw_water_world(self,canvas,top = 0.25): canvas.draw_image(self.water_world,(997/2,647/2),(997,647),(self.dimensions[0]/2,(top+(1-top)/2)*self.dimensions[1]),(self.dimensions[0],self.dimensions[1]*(1-top))) def draw(self, canvas): delta = time.time()-self.lastFrameTime self.lastFrameTime = time.time() print("fps: "+ str(1/delta)) self.background(canvas,20,4,1,0.3,0.03,"rgb(0,0,100)") self.background(canvas,20,3,-0.6,0.3,0.04,"rgb(0,0,150)") self.draw_water_world(canvas) self.draw_carol(canvas,0.2) self.draw_carol(canvas,0.7) self.draw_perl(canvas,0.5) self.background(canvas,20,2,0.2,0.3,0.05,"rgb(0,0,250)") big = self.poly(40,2,0.2,0.3,0.05) #rgb(0,0,250) middle = self.poly(40,3,-0.6,0.3,0.04) # rgb(0,0,150) small = self.poly(40,4,1,0.3,0.03) #rgb(0,0,100) middles = self.sub(40,middle,big,big) smalls = self.sub(40,small,middle,big) self.draw_wave_parts(canvas,middles,"rgb(0,0,150)") self.draw_wave_parts(canvas,smalls,"rgb(0,0,100)") self.looping_clouds(canvas,0.05,0.2) self.draw_sun(canvas,0.3) self.looping_clouds(canvas,0.03,0.25)
class Background: def __init__(self, dimensions, time): addr = os.getcwd() self.time = time self.lastFrameTime = self.time.time() self.dimensions = dimensions # resource addresses self.clouds = simplegui.load_image("file:///" + addr + "/images/background_clouds.png") self.sun = simplegui.load_image("file:///" + addr + "/images/sun.png") self.water_world = simplegui.load_image( "file:///" + addr + "/images/underwater-seamless-landscape-cartoon-background-vector-7524975.png" ) # establish background elements as spritesheet objects with their spritesheet image self.bubbles = SS("file:///" + addr + "/images/Bubble1.png", (6, 5), time=1250, scale=0.22, timehand=self.time) self.carol = SS("file:///" + addr + "/images/carol.png", (5, 1), time=800, scale=0.22, timehand=self.time) self.perl = SS("file:///" + addr + "/images/pearl.png", (3, 3), time=3000, scale=0.22, looping=False, timehand=self.time) self.bWaveParts = [] self.mWaveParts = [] self.sWaveParts = [] self.pollycount = 35 t = threading.Thread(target=self.update, args=()) t.start() # draw a wave's polygons to the screen def draw_wave_parts(self, canvas, poly, color): for path in poly: if len(path) > 2: canvas.draw_polygon(path.tolist(), 1, color, color) # draw static sun image to screen def draw_sun(self, canvas, height): canvas.draw_image( self.sun, (250, 250), (500, 500), (self.dimensions[0] - self.dimensions[1] * height / 2, self.dimensions[1] * height / 2), (self.dimensions[1] * height, self.dimensions[1] * height)) # draws clouds animation to sky def looping_clouds(self, canvas, frequency, height): offset = self.lastFrameTime % (1 / frequency) * frequency dim = (2400, 300) cen = (1200, 150) width = math.floor(dim[0] / dim[1] * height * self.dimensions[1]) canvas.draw_image( self.clouds, cen, dim, (width / 2 - offset * width, height * self.dimensions[1] / 2), (width, height * self.dimensions[1])) canvas.draw_image(self.clouds, cen, dim, (width / 2 + width - offset * width, height * self.dimensions[1] / 2), (width, height * self.dimensions[1])) canvas.draw_image(self.clouds, cen, dim, (width / 2 + width * 2 - offset * width, height * self.dimensions[1] / 2), (width, height * self.dimensions[1])) # drawing background elements through the spritesheet object draw handler def draw_carol(self, canvas, x=0.5): self.carol.draw(canvas, center=(x * self.dimensions[0], self.dimensions[1] - self.carol.adim[1] * self.carol.scale / 2)) self.bubbles.draw( canvas, center=(x * self.dimensions[0], self.dimensions[1] - self.bubbles.adim[1] * self.bubbles.scale / 2)) def draw_perl(self, canvas, x=0.5): self.perl.draw(canvas, center=(x * self.dimensions[0], self.dimensions[1] - self.perl.adim[1] * self.perl.scale / 2)) def draw_water_world(self, canvas, top=0.25): canvas.draw_image(self.water_world, (997 / 2, 647 / 2), (997, 647), (self.dimensions[0] / 2, (top + (1 - top) / 2) * self.dimensions[1]), (self.dimensions[0], self.dimensions[1] * (1 - top))) # draw method to call above 3 methods as well as generate the background waves and call methods to draw clouds/sun def update(self): if self.time.check_running(): #while the game is running # establish 3 different wave paths self.lastFrameTime = self.time.time() big = poly(self.lastFrameTime, self.dimensions, self.pollycount, 2, 0.2, 0.3, 0.05) # rgb(0,0,250) middle = poly(self.lastFrameTime, self.dimensions, self.pollycount, 3, -0.6, 0.3, 0.04) # rgb(0,0,150) small = poly(self.lastFrameTime, self.dimensions, self.pollycount, 4, 1, 0.3, 0.03) # rgb(0,0,100) self.mWaveParts = sub( middle, big) #subtract the bigger wave from the middle size one # subtract the combined top wave from the smallest one self.sWaveParts = sub(small, maxpols(middle, big)) self.bWaveParts = [ numpy.concatenate((big, [[self.dimensions[0], 0], [0, 0]])) ] # if running faster than 30hz sleep the correct amount of time # draw method to call above 3 methods as well as generate the background waves and call methods to draw clouds/sun def draw(self, canvas): self.draw_water_world(canvas) #draw the large background image # draw the animating features at the bottom of the screen #self.draw_carol(canvas,0.2) #self.draw_carol(canvas,0.7) #self.draw_perl(canvas,0.5) # drawing the background waves self.draw_wave_parts( canvas, self.bWaveParts, "rgb(0,0,250)") #draws the front wave as a full polygon big self.draw_wave_parts( canvas, self.mWaveParts, "rgb(0,0,150)" ) #draw these wave sections on behind main polygon medium self.draw_wave_parts( canvas, self.sWaveParts, "rgb(0,0,100)") #draw the smaller waves sections small