示例#1
0
class CollisionObject(object):
    def __init__(self,
                 label="Default",
                 pos: Vector2D = Vector2D(0, 0),
                 scale: Vector2D = Vector2D(0, 0),
                 center: Vector2D = Vector2D(0, 0),
                 colour: Colour = (0, 0, 0)):
        self.label = label
        self.pos: Vector2D = pos
        self.scale: Vector2D = scale
        self.center: Vector2D = center
        self.colour: Colour = colour
        self.visible = False
        global_pos: Vector2D = self.pos + self.center
        self.rect = Rect(global_pos.x, global_pos.y, self.scale.x,
                         self.scale.y)

    def update(self):
        global_pos: Vector2D = self.pos + self.center
        self.rect = Rect(global_pos.x, global_pos.y, self.scale.x,
                         self.scale.y)

    def draw(self, screen):
        if self.visible:
            pygame.draw.rect(screen, self.colour, self.rect, 5)

    def is_colliding(self, other):
        return self.rect.colliderect(other.rect)

    def is_colliding_any(self, others: list):
        others = [o.rect for o in others]
        return self.rect.collidelist(others)

    def is_colliding_all(self, others: list):
        others = [o.rect for o in others]
        return self.rect.collidelistall(others)
示例#2
0
def grid_select(state, start_pos, steps, end_pos_func=None, COLOR=LIGHT_BLUE):
    x, y = start_pos
    speed = steps
    pos_list = []
    rect_list = []
    for i in range((speed * 2) + 1):
        for n in range((speed * 2) + 1):
            p = ((x + i - speed), (y + n - speed))
            pos_list.append(p)
            pixel_p = tuple(axis * state.map.unit for axis in p)
            rect_list.append(Rect(pixel_p, state.map.unit_t))
    state.draw()
    end_pos_found = False
    for i in range(len(pos_list)):
        p = pos_list[i]
        r = rect_list[i]
        if end_pos_func:
            if end_pos_func(p):
                pygame.draw.rect(state.screen, COLOR, r, 1)
                end_pos_found = True
        else:
            pygame.draw.rect(state.screen, COLOR, r, 1)
    pygame.display.flip()
    if end_pos_func and not end_pos_found:
        state._print('End position not found, cannot perform action')
        return
    while 1:
        event = pygame.event.wait()
        if event.type == pygame.KEYUP:
            if event.key == 27:  # esc
                return None
        if event.type == pygame.MOUSEBUTTONUP:
            r = Rect(event.pos, (1, 1))
            index = r.collidelist(rect_list)
            if not index == -1:
                return state.map.grid_pos(event.pos)
def advance_frame(input_get=pygame.event.get):
    global PLATFORMS, HATS, SPIKES, SPRINGS, ENEMIES, _ENEMIES, FLAGS, CHEESE, BACK, SPAWN
    global  X, Y, x_vel, y_vel, DOOR, HAT, STATE, CROUCH, mov, hub, DIR
    global counter, dframe, IGT, endcard
    plats = []
    allplats = []
    for pos, dim, idx in PLATFORMS:
        allplats.append(Rect(pos, (dim[0]*32, dim[1]*32)))
        if isnear(pos, dim): plats.append(Rect(pos, (dim[0]*32, dim[1]*32)))
    # update counters/clock
    counter += 1
    dframe = (dframe + 1) % 12
    IGT += CLOCK.tick(30)
    # draw update screen
    adjust_scroller()
    SCREEN.blit(get_screen(), (0, 0))
    SCREEN.blit(get_HUD(), (0, 0))
    pygame.display.update()

    # evaluate input
    jmp = 0
    door = 0
    for e in input_get():
        if e.type == QUIT or e.type == KEYDOWN and e.key == K_ESCAPE: quit()
        if e.type == KEYDOWN:
            if e.key == K_LEFT: mov = max(mov - 1, -1)
            if e.key == K_RIGHT: mov = min(mov + 1, 1)
            if e.key == K_DOWN: CROUCH = min(CROUCH+1, 1)
            if e.key == K_SPACE: jmp += 1
            if e.key == K_UP: door = True
        if e.type == KEYUP:
            if e.key == K_LEFT: mov = min(mov+1, 1)
            if e.key == K_RIGHT: mov = max(mov-1, -1)
            if e.key == K_DOWN: CROUCH = max(CROUCH-1, 0)

    # change state, update movement
    JUMP = _JUMP * 2 if HAT == "baseball" else _JUMP
    if STATE == "dmg":
        if counter == 1:
            sounds["death"].stop()
            sounds["death"].play()

        if counter < 10: return
        STATE = "stand"
        X, Y = SPAWN
        x_vel, y_vel = 0, 0
        HAT = None
        ENEMIES = deepcopy(_ENEMIES)
    elif jmp and (STATE in ["stand", "run0", "run1", "slide", "wall"] or HAT == "propeller"):
        sounds["jump"].stop()
        sounds["jump"].play()
        if HAT == "propeller": y_vel = JUMP
        if STATE == "wall":
            y_vel = JUMP
            DIR *= -1
            x_vel = max(SPEED * DIR, x_vel) if DIR > 0 else min(SPEED * DIR, x_vel)
        else:
            STATE = "squat"
            counter = 0
    elif STATE == "squat":
        if counter >= 3: y_vel = JUMP
    elif CROUCH: STATE = "crouch"
    elif mov and STATE not in ['crouch']:
        if DIR == mov: x_vel = max(SPEED * DIR, x_vel) if DIR > 0 else min(SPEED * DIR, x_vel)
        elif not x_vel or abs(x_vel) <= 3: DIR = mov
        if (x_vel > 0 and mov < 0) or (x_vel < 0 and mov > 0): STATE == "slide" 
    elif x_vel == 0: STATE = "stand"
    else: STATE = "slide"
        
    if mov and not STATE in ["run0", "run1", "crouch", "squat"]:
        if ((x_vel > 0 and mov < 0) or (x_vel < 0 and mov > 0)): STATE = "slide"
        else:
            STATE = "run0"
            counter = 0

    if STATE.startswith("run") and counter >= 5:
        STATE = "run" + str((int(STATE[-1]) + 1) % 2)
        counter = 0

    if y_vel < 0: STATE = "jump0"
    if y_vel > 0: STATE = "jump1"

    # friction and gravity
    if x_vel and not STATE.startswith("jump"): x_vel += friction if x_vel < 0 else -1
    y_vel += grav

    if STATE in ["jump1", "run0", "run1", "stand", "slide"] and HAT == "sombraro" and not CROUCH: y_vel = 0

    # animate relevent actors
    for spring in SPRINGS:
        if spring[3]: spring[3] -= 1

    # enemy logic
    remove = []
    for i in range(len(ENEMIES)):
        pos, name, d, f , c = ENEMIES[i]
        if not isnear(pos): continue
        c += 1
        if name == "bone":
            if c % 2:
                f = (f + 1) % 2
                pos = (pos[0] + BONESPEED, pos[1]) if d == 0 else (pos[0] - BONESPEED, pos[1])
            if c > 50: remove.append(i)
            
        if name == "skeleton":
            if abs(pos[0] - X) < 410:
                if f == 0: d = 0 if X > pos[0] else 1
                if c >= 8 and f == 0: f = 1
                elif c >= 30 and f == 1:
                    sounds["throw"].stop()
                    sounds["throw"].play()
 
                    f = 2
                    ENEMIES.append( [pos, 'bone', d, 0, 0] )
                elif c > 40: f, c = 0, 0
            else: f, c = 0, 0

        if name == "zombie":
            if c % 4 == 0 and abs(pos[0] - X) < 512:
                hitbox = Rect((pos[0]+8, pos[1]), (32, 64))
                if d == 0: footbox = Rect((pos[0] + 32 + ZOMBIESPEED, pos[1] + 64), (10, 10)) 
                else: footbox = Rect((pos[0] - ZOMBIESPEED, pos[1]+64), (10, 10))
                
                if hitbox.collidelist(allplats) == -1:
                    d = 0 if X > pos[0] else 1
                f = (f + 1) % 2
                pos = (pos[0] + ZOMBIESPEED, pos[1]) if d == 0 else (pos[0] - ZOMBIESPEED, pos[1])
                if hitbox.collidelist(allplats) != -1 or footbox.collidelist(allplats) == -1:
                    pos = (pos[0] - ZOMBIESPEED*2, pos[1]) if d == 0 else (pos[0] + ZOMBIESPEED*2, pos[1])

        if name == "snake":
            hitbox = Rect(pos, (64, 16))
            if c % 4 == 0:
                f = (f + 1) % 2
                pos = (pos[0] + SNAKESPEED, pos[1]) if d == 0 else (pos[0] - SNAKESPEED, pos[1])
                if hitbox.collidelist(allplats) != -1:
                    d = (d + 1) % 2
                    pos = (pos[0] + SNAKESPEED*2, pos[1]) if d == 0 else (pos[0] - SNAKESPEED*2, pos[1])

        if name == "ghost":
            d = 0 if X > pos[0] else 1
            if (d == 1 and DIR == 1) or (d == 0 and DIR == -1): f = 1
            else: f = 0
            if abs(pos[0] - X) + abs(pos[1] - Y) < 800 and f == 0:
                if abs(pos[0] - X) > 30:
                    x = -1 if X < pos[0] else 1
                else: x = 0
                if abs(pos[1] - Y) > 30:
                    y = -1 if Y < pos[1] else 1
                else: y = 0
                pos = (pos[0]+x, pos[1]+y)
                
                    
        ENEMIES[i] = [pos, name, d, f, c]

    for i in remove[::-1]: ENEMIES.pop(i) 
    
    # hit detection - platforms
    hitbox = Rect((X, Y), (32, 64)) if STATE != "crouch" else Rect((X, Y+32), (32, 32))
    checklist = plats
    if hitbox.collidelist(checklist) != -1:
        STATE = "dmg"
        return
    if x_vel:
        while hitbox.move(x_vel, 0).collidelist(checklist) != -1:
            if STATE.startswith("jump"): STATE = "wall"
            x_vel += 1 if x_vel < 0 else -1
    if y_vel:
        while hitbox.move(0, y_vel).collidelist(checklist) != -1: y_vel += 1 if y_vel < 0 else -1
    if x_vel and y_vel:
        while hitbox.move(x_vel, y_vel).collidelist(checklist) != -1:
            y_vel += 1 if y_vel < 0 else -1
            x_vel += 1 if x_vel < 0 else -1
    #                 hats
    checklist = [Rect(pos, (46, 46)) for pos, hat in HATS]
    i = hitbox.collidelist(checklist)
    if i != -1: HAT = HATS[i][1]
    #                 flags
    checklist = [Rect(pos, (46, 64)) for pos in FLAGS]
    i = hitbox.collidelist(checklist)
    if i != -1: SPAWN = FLAGS[i]
    #                 spikes and enemies
    checklist = []
    for pos, d in SPIKES:
        if not isnear(pos): continue
        if d == 0: checklist += [Rect((pos[0]+8, pos[1]), (16, 16)), Rect((pos[0], pos[1]+16), (32, 16))]
        elif d == 1: checklist += [Rect((pos[0], pos[1]+8), (16, 16)), Rect((pos[0]+16, pos[1]), (16, 32))]
        elif d == 2: checklist += [Rect((pos[0], pos[1]), (32, 16)), Rect((pos[0]+8, pos[1]+16), (16, 16))]
        elif d == 3: checklist += [Rect((pos[0], pos[1]), (16, 32)), Rect((pos[0]+16, pos[1]+8), (32, 16))]

    for pos, name, d, f, c in ENEMIES:
        if not isnear(pos): continue
        if name in ["bone", "ghost"]: checklist.append(Rect(pos, (32, 32)))
        elif name == "snake": checklist.append(Rect(pos, (64, 16)))
        else: checklist.append(Rect(pos, (32, 64)))
    i = hitbox.collidelist(checklist)
    if i != -1:
        STATE = "dmg"
        counter = 0
    #                 springs
    checklist = [Rect(pos, (48, 48)) for pos, d, s, f in SPRINGS]
    i = hitbox.collidelist(checklist)
    if i != -1:
        if SPRINGS[i][3] != 10:
            sounds["spring"].stop()
            sounds["spring"].play()

        SPRINGS[i][3] = 10
        if SPRINGS[i][1] == 0: y_vel = 0 - SPRINGS[i][2]
        elif SPRINGS[i][1] == 2: y_vel = SPRINGS[i][2]
        elif SPRINGS[i][1] == 3:
            DIR = 1
            x_vel = SPRINGS[i][2]
        elif SPRINGS[i][1] == 1:
            DIR = -1
            x_vel = -1 * SPRINGS[i][2]
    #                 cheese
    checklist = []
    for pos, idx in CHEESE:
        if idx == 3: checklist.append(Rect(pos, (64, 64)))
        else: checklist.append(Rect(pos, (32, 32)))
    i = hitbox.collidelist(checklist)
    if i != -1:
        sounds["get"].stop()
        sounds["get"].play()

        if not CHEESE[i][1] == 3: INV.append(CHEESE.pop(i))
        else:
            n = H
            end = True
            while end:
                CLOCK.tick(30)
                if n >= 0: n -= 10
                SCREEN.blit(get_screen(), (0, 0))
                SCREEN.blit(endcard, (0, n))
                pygame.draw.rect(SCREEN, (200, 200, 200), Rect((380, n + 530), (256, 104)))
                SCREEN.blit(HEL64.render(str(IGT // 60000) +":"+ ("0" + str(IGT // 1000 % 60))[-2:], 0, (0, 0, 0)), (400, n + 550))
                pygame.display.update()
                for e in pygame.event.get():
                    if e.type == QUIT or e.type == KEYDOWN and e.key == K_ESCAPE: quit()
                    if e.type == KEYDOWN:
                        if e.key == K_LEFT: mov += -1
                        if e.key == K_RIGHT: mov += 1
                        if e.key == K_DOWN: CROUCH += 1
                        if e.key == K_SPACE and n <= 0:
                            end = False
                            load_level(hublvl)
                            hub=True
                    if e.type == KEYUP:
                        if e.key == K_LEFT: mov -= -1
                        if e.key == K_RIGHT: mov -= 1
                        if e.key == K_DOWN: CROUCH -= 1
    #                 door
    if hub:
        doorlist = [Rect((256+(i*256), 64), (64, 64)) for i in range(len(LEVELS))]
        di = hitbox.collidelist(doorlist)
    # enter door
    if door and (hitbox.colliderect(Rect(DOOR, (64, 64))) or (hub and di != -1 and len(INV)>=needs[di] )):
        sounds["door"].stop()
        sounds["door"].play()

        n = 2
        if not hub: X, Y = DOOR[0] + 16, DOOR[1]
        adjust_scroller()
        STATE = "jump1"
        while n < 980:
            surf = rotate(get_screen(), n)
            SCREEN.blit(surf, ((W-surf.get_width())//2, (H - surf.get_height())//2))
            n += n // 2
            CLOCK.tick(30)
            pygame.display.update()
            for e in pygame.event.get():
                if e.type == QUIT or e.type == KEYDOWN and e.key == K_ESCAPE: quit()
                if e.type == KEYDOWN:
                    if e.key == K_LEFT: mov += -1
                    if e.key == K_RIGHT: mov += 1
                    if e.key == K_DOWN: CROUCH += 1
                if e.type == KEYUP:
                    if e.key == K_LEFT: mov -= -1
                    if e.key == K_RIGHT: mov -= 1
                    if e.key == K_DOWN: CROUCH -= 1
    
        if hub and di != -1:
            load_level(LEVELS[di])
            hub = False
        else:
            load_level(hublvl)
            hub = True
    # apply final calculated movement
    X += x_vel
    Y += y_vel
            if abs(pos[0] - X) < 410:
                if f == 0: d = 0 if X > pos[0] else 1
                if c >= 8 and f == 0: f = 1
                elif c >= 30 and f == 1:
                    f = 2
                    ENEMIES.append( [pos, 'bone', d, 0, 0] )
                elif c > 40: f, c = 0, 0
            else: f, c = 0, 0

        if name == "zombie":
            if c % 4 == 0 and abs(pos[0] - X) < 512:
                hitbox = Rect((pos[0]+8, pos[1]), (32, 64))
                if d == 0: footbox = Rect((pos[0] + 32 + ZOMBIESPEED, pos[1] + 64), (10, 10)) 
                else: footbox = Rect((pos[0] - ZOMBIESPEED, pos[1]+64), (10, 10))
                
                if hitbox.collidelist(allplats) == -1:
                    d = 0 if X > pos[0] else 1
                f = (f + 1) % 2
                pos = (pos[0] + ZOMBIESPEED, pos[1]) if d == 0 else (pos[0] - ZOMBIESPEED, pos[1])
                if hitbox.collidelist(allplats) != -1 or footbox.collidelist(allplats) == -1:
                    pos = (pos[0] - ZOMBIESPEED*2, pos[1]) if d == 0 else (pos[0] + ZOMBIESPEED*2, pos[1])

        if name == "snake":
            hitbox = Rect(pos, (64, 16))
            if c % 4 == 0:
                f = (f + 1) % 2
                pos = (pos[0] + SNAKESPEED, pos[1]) if d == 0 else (pos[0] - SNAKESPEED, pos[1])
                if hitbox.collidelist(allplats) != -1:
                    d = (d + 1) % 2
                    pos = (pos[0] + SNAKESPEED*2, pos[1]) if d == 0 else (pos[0] - SNAKESPEED*2, pos[1])