Пример #1
0
class PySnake(MyGame):
    "贪吃蛇游戏"

    def __init__(self):
        super(PySnake, self).__init__(GAME_NAME, SCREEN_SIZE, FPS,
                                      "resources/Minecraft.ttf", 16,
                                      "resources/pysnake.png")
        self.background.fill(BACKGROUND_COLOR)
        for i in range(CELL_SIZE, SCREEN_WIDTH, CELL_SIZE):
            pygame.draw.line(self.background, GRID_COLOR, (i, 0),
                             (i, SCREEN_HEIGHT))
        for i in range(CELL_SIZE, SCREEN_HEIGHT, CELL_SIZE):
            pygame.draw.line(self.background, GRID_COLOR, (0, i),
                             (SCREEN_WIDTH, i))

        self.field = Field(self, COLUMNS, ROWS)
        self.apple_counter = 0
        self.apple = Apple(self)
        # self.snake = Snake(self)
        self.snake = Snake(self, SNAKE_DEFAULT_X, SNAKE_DEFAULT_Y,
                           SNAKE_DEFAULT_LENGTH, RIGHT, SNAKE_DEFAULT_SPEED,
                           SNAKE_COLOR_SKIN, SNAKE_COLOR_BODY,
                           SNAKE_COLOR_HEAD)

        # 控制按键设定
        self.key_bind(KEY_EXIT, self.quit)
        self.key_bind(KEY_UP, self.snake.turn, direction=UP)
        self.key_bind(KEY_DOWN, self.snake.turn, direction=DOWN)
        self.key_bind(KEY_LEFT, self.snake.turn, direction=LEFT)
        self.key_bind(KEY_RIGHT, self.snake.turn, direction=RIGHT)
        self.key_bind(pygame.K_EQUALS, self.snake.speed_up)
        self.key_bind(pygame.K_MINUS, self.snake.speed_down)
        self.key_bind(KEY_RESPAWN, self.restart)

        self.add_draw_action(self.show_score)

    def restart(self):
        if not self.snake.alive:
            self.apple_counter = 0
            self.field.clear()  # 移除尸体
            self.apple.drop()
            self.snake.respawn()

    def show_score(self):
        text = "Apple {}".format(self.apple_counter)
        output = self.font.render(text, True, (255, 255, 33))
        self.screen.blit(output, (0, 0))

        if not self.snake.alive:
            text = " GAME OVER"
            output = self.font.render(text, True, (255, 33, 33), WHITE)
            self.screen.blit(output, (320 - 54, 240 - 10))
            text = " press R to restart"
            output = self.font.render(text, True, GREY, DARK_GREY)
            self.screen.blit(output, (320 - 94, 260 - 10))

        if not self.running and self.snake.alive:
            text = " GAME PAUSED"
            output = self.font.render(text, True, LIGTH_GREY, DARK_GREY)
            self.screen.blit(output, (320 - 54, 240 - 10))
Пример #2
0
class Saver():
    def __init__(self, balls=int(random.random() * 100), trail=" "):
        self.field = Field(title="Term Saver")
        self.balls = [Ball(x=int(random.random() * self.field.x-1)+1, y=int(random.random() * self.field.y-1)+1) for x in range(balls)]
        self.speed = 0.009
        self.trail = trail
        return

    def update(self):
        for ball in self.balls:
            hitWall = self.walled(ball)

            if hitWall: # wall collision
                ball.bounce(hitWall)

            # ball collision

            self.clearTrail(ball, self.trail, True)
            ball.move()

            self.field.write_at(item=ball.image, coords=ball.getPosition())

        # clear the field randomly (.1% chance)
        if random.choice(range(1000)) == 1:
            self.field.clear()
        self.field.deploy()
        return

    def walled(self, ball):
        direction = []
        if ball.x < 1:
            direction.append('right')
        elif ball.x >= self.field.x-1:
            direction.append('left')

        if ball.y < 1:
            direction.append('down')
        elif ball.y >= self.field.y-1:
            direction.append('up')

        if len(direction):
            return ' '.join(direction)
        return None

    def run(self):
        run = 1
        while run:
            c = self.field.display.getch()
            if c == ord('q'):
                run = 0
            self.update()
            time.sleep(self.speed)
        self.field.destroy()
        return

    def clearTrail(self, obj, remains=" ", centered=False):
        for i in range(len(obj.image)):
            self.field.write_at(item=remains, coords=[obj.x+i, obj.y], centered=centered)
        return
Пример #3
0
class DiamondShift:
  def __init__(self):
    pygame.init()
    pygame.mouse.set_visible(0)
    self.screen = pygame.display.set_mode((320, 240), 0, 32)
    self.gems = pygame.image.load("gems.png").convert_alpha()
    self.bg = pygame.image.load("bg.png").convert_alpha()
    self.gems = self.separate_gems(self.gems)
    self.gemsize = self.gems[0].get_width()
    self.grey = (75, 75, 75)
    self.cursor = pygame.Surface((self.gemsize, self.gemsize)).convert_alpha()
    self.cursor.fill(self.grey)
    self.font = pygame.font.Font(None, 24)
    self.score = 0
    self.field = Field(8, 8, len(self.gems) - 1)
    self.ctrl = Control(Point(7, 7))
    self.state = 'standby' # | swap | swap-back | fill | check | score
    self.swap = None 
    self.winners = None

  def run(self):
    while self.loop():
      self.read()
      self.step()
      # self.draw()

  def loop(self):
    return not self.ctrl.quit

  def read(self):
    update(self.ctrl)

  def step(self):
    delay = 16

    if self.state == 'standby':
      if self.ctrl.direction:
        self.swap = deepcopy((self.ctrl.pos, self.ctrl.direction))
        self.state = 'swap'
  
    elif self.state == 'swap':
      self.field.swaps(self.swap[0].x, self.swap[0].y, self.swap[1])
      self.winners = self.field.find_winners()
      if self.winners:
        self.state = 'score'
      else:
        self.state = 'swap-back'
      delay = 150
      
    elif self.state == 'swap-back':
      self.field.swaps(self.swap[0].x, self.swap[0].y, self.swap[1])
      self.state = 'standby'
      delay = 150
      
    elif self.state == 'fill':
      again = self.field.fall()
      again = self.field.pour() or again
      if not again:
        self.state = 'check'
      delay = 150
      
    elif self.state == 'check':
      self.winners = self.field.find_winners()
      if self.winners:
        self.state = 'score'
      else:
        self.state = 'standby'
      delay = 150
      
    elif self.state == 'score':
      def score(n):
        return (n - 1)**2
      self.score += score(len(self.winners))
      self.field.clear(self.winners)
      self.state = 'fill'
      delay = 150

    self.draw()
    pygame.time.delay(delay)

  def draw(self):
    xoffset = 11
    yoffset = 24
    size = self.gems[0].get_width()
    self.screen.blit(self.bg,(0,0))
    self.screen.blit(self.cursor, (xoffset + self.gemsize * self.ctrl.pos.x, yoffset + self.gemsize * self.ctrl.pos.y))
    for x in xrange(self.field.width):
      for y in xrange(self.field.height):
        self.screen.blit(self.gems[self.field.map.get((x, y), 0)],(xoffset + x * size, yoffset + y * size))
    self.screen.blit(self.font.render("%d" % self.score, 1, (255, 255, 255)), (15, 3))
    pygame.display.flip()

  def separate_gems(self, gems):
    ng = []
    size = self.gems.get_height()
    count = self.gems.get_width()/gems.get_height()
    for c in xrange(count):
      s = pygame.Surface((size,size),pygame.SRCALPHA, 32).convert_alpha()
      s.blit(self.gems, (0, 0), pygame.Rect(c * size, 0, (c + 1) * size, size))
      ng.append(s)
    return ng
Пример #4
0
class MaskSaver(Saver):

    def __init__(self, balls=int(random.random() * 100), trail=" ", mask=None):
        self.field = Field(title="Term Saver")
        self.balls = [Ball(x=int(random.random() * self.field.x-1)+1, y=int(random.random() * self.field.y-1)+1) for x in range(balls)]
        self.speed = 0.009
        self.trail = trail
        self.addMask(mask)

    def addMask(self, mask):
        """
        Given a 2D array depciting some image to mask out
        e.g. a box or a name or a picture of peeve
        shrink or fatten it up to fit the shape of our field/grid
        dimensions must be at least.... 4 x 4 ? e.g.
        
        . . . .
        . x x .
        . x x .
        . . . .

        The players on the field should never write to 
        the 'x'd out areas.

        but our grid will probably be larger than this...
        so what is the maths behind making this fit properly?
        e.g. a 4 x 4 mask supplied for a 64 x 64 grid
        let's start small and just double it
        
        . . . . . . . .      . . . . . . . .      . . . . . . . .
        . . . . . . . .      . x x x x x x .      . . . . . . . .
        . . . . . . . .      . x x x x x x .      . . x x x x . .
        . . . . . . . .      . x x x x x x .      . . x x x x . .
        . . . . . . . .  =>  . x x x x x x .  or  . . x x x x . .
        . . . . . . . .      . x x x x x x .      . . x x x x . .
        . . . . . . . .      . x x x x x x .      . . . . . . . .
        . . . . . . . .      . . . . . . . .      . . . . . . . .
                                  bad                  good

        I think the result where we look at the proportionality works best.
        The first transformation has a single border like the original,
        and the second maintains the proportions (e.g. 50%).

        What happens when it's more awkward?

        . . . . . .      . . . . . .      . . . . . .
        . . . . . .  =>  . x x x x .  or  . . x x . .
        . . . . . .      . . . . . .      . . . . . .
                             bad              good

        I still like the second transformation.
        So I guess when taking 1/2 of an odd, round down?
        """
        pass

    def update(self):
        for ball in self.balls:
            hitWall = self.walled(ball)

            if hitWall: # wall collision
                ball.bounce(hitWall)

            # ball collision

            self.clearTrail(ball, self.trail, True)
            ball.move()

            self.field.write_at(item=ball.image, coords=ball.getPosition())

        # clear the field randomly (.1% chance)
        if random.choice(range(1000)) == 1:
            self.field.clear()

        self.field.deploy()
Пример #5
0
class Game:
    def __init__(self):
        self.field = Field()
        self.walls = []
        self.pongs = []
        self.balls = []

        self.fps = 15

        self.__create_walls()
        self.__create_pong()
        self.__create_ball()

        self.snake = Snake(40, 15)

        self.__game_loop()

    def __game_loop(self):
        threading.Thread(target=self.__render, daemon=True).start()
        self.__update()

    def __update(self):
        while True:
            # update game logic every x seconds

            # TODO game_over = False

            # TODO process_keyboard_input()

            # TODO check collision_ball()
            # TODO check_collision_snake()
            # TODO check_collision_pong()

            self.__update_ball()
            self.__update_pong()
            self.snake.update()

            time.sleep(.150)

    def __render(self):
        stdscr = curses.initscr()

        curses.start_color()
        curses.use_default_colors()
        try:
            for i in range(0, curses.COLORS):
                curses.init_pair(i, i, -1)
        except Exception:
            pass

        while True:
            stdscr.scrollok(True)
            stdscr.clear()
            self.field.clear()

            for wall in self.walls:
                wall.render(self.field)

            for pong in self.pongs:
                pong.render(self.field)

            for ball in self.balls:
                ball.render(self.field)

            self.snake.render(self.field)

            self.field.render(stdscr)
            stdscr.refresh()

            time.sleep(1 / self.fps)

    def __create_walls(self):
        for y in range(self.field.get_height()):
            for x in range(self.field.get_width()):
                if (x == 0 or x == 1 or y == 0
                        or x > self.field.get_width() - 3
                        or y > self.field.get_height() - 2):
                    self.walls.append(Wall(x, y))

    def __create_pong(self):
        for y in range(self.field.get_height()):
            for x in range(self.field.get_width()):
                if ((x == 4 or x == 5) and (y >= 13 and y <= 17)):
                    self.pongs.append(Pong(x, y))

    def __create_ball(self):
        for y in range(self.field.get_height()):
            for x in range(self.field.get_width()):
                if ((x == 30) and (y == 15)):
                    self.balls.append(Ball(x, y))

    def __update_pong(self):
        up = self.pongs[2].get_y() >= self.balls[0].get_y()
        for pong in self.pongs:
            if up: pong.move_up()
            else: pong.move_down()

    def __update_ball(self):
        self.balls[0].move_left()
class DiamondShift:
    def __init__(self):
        pygame.init()
        pygame.mouse.set_visible(0)
        self.screen = pygame.display.set_mode((320, 240), 0, 32)
        self.gems = pygame.image.load("gems.png").convert_alpha()
        self.bg = pygame.image.load("bg.png").convert_alpha()
        self.gems = self.separate_gems(self.gems)
        self.gemsize = self.gems[0].get_width()
        self.grey = (75, 75, 75)
        self.cursor = pygame.Surface(
            (self.gemsize, self.gemsize)).convert_alpha()
        self.cursor.fill(self.grey)
        self.font = pygame.font.Font(None, 24)
        self.score = 0
        self.field = Field(8, 8, len(self.gems) - 1)
        self.ctrl = Control(Point(7, 7))
        self.state = 'fill'  # | swap | swap-back | fill | check | score
        self.swap = None
        self.winners = None

    def run(self):
        while self.loop():
            self.read()
            self.step()
            # self.draw()

    def loop(self):
        return not self.ctrl.quit

    def read(self):
        update(self.ctrl)

    def step(self):
        delay = 16

        if self.state == 'standby':
            if self.ctrl.direction:
                self.swap = deepcopy((self.ctrl.pos, self.ctrl.direction))
                self.state = 'swap'

        elif self.state == 'swap':
            self.field.swaps(self.swap[0].x, self.swap[0].y, self.swap[1])
            self.winners = self.field.find_winners()
            if self.winners:
                self.state = 'score'
            else:
                self.state = 'swap-back'
            delay = 150

        elif self.state == 'swap-back':
            self.field.swaps(self.swap[0].x, self.swap[0].y, self.swap[1])
            self.state = 'standby'
            delay = 150

        elif self.state == 'fill':
            again = self.field.fall()
            again = self.field.pour() or again
            if not again:
                self.state = 'check'
            delay = 150

        elif self.state == 'check':
            self.winners = self.field.find_winners()
            if self.winners:
                self.state = 'score'
            else:
                self.state = 'standby'
            delay = 150

        elif self.state == 'score':

            def score(n):
                return (n - 1)**2

            self.score += score(len(self.winners))
            self.field.clear(self.winners)
            self.state = 'fill'
            delay = 150

        self.draw()
        pygame.time.delay(delay)

    def draw(self):
        xoffset = 11
        yoffset = 24
        size = self.gems[0].get_width()
        self.screen.blit(self.bg, (0, 0))
        self.screen.blit(self.cursor,
                         (xoffset + self.gemsize * self.ctrl.pos.x,
                          yoffset + self.gemsize * self.ctrl.pos.y))
        for x in xrange(self.field.width):
            for y in xrange(self.field.height):
                self.screen.blit(self.gems[self.field.map.get((x, y), 0)],
                                 (xoffset + x * size, yoffset + y * size))
        self.screen.blit(
            self.font.render("%d" % self.score, 1, (255, 255, 255)), (15, 3))
        pygame.display.flip()

    def separate_gems(self, gems):
        ng = []
        size = self.gems.get_height()
        count = self.gems.get_width() / gems.get_height()
        for c in xrange(count):
            s = pygame.Surface((size, size), pygame.SRCALPHA,
                               32).convert_alpha()
            s.blit(self.gems, (0, 0),
                   pygame.Rect(c * size, 0, (c + 1) * size, size))
            ng.append(s)
        return ng
Пример #7
0
class Program:
    """The main class for playing a program"""
    def __init__(self, resolution=(1366, 768), fullscreen=True):
        fullscreen = pygame.FULLSCREEN if fullscreen else 0
        self.resolution = resolution
        try:
            self.window = pygame.display.set_mode(resolution, fullscreen)
        except Exception as e:
            Tk().withdraw()
            messagebox.showerror('Ошибка!', e)
            raise e
        pygame.display.set_caption('Life by BUS410')
        self.cols = (resolution[0] - UI_WIDTH) // 10
        self.rows = resolution[1] // 10
        self.field = Field(resolution[0] - UI_WIDTH,
                           resolution[1],
                           self.cols,
                           self.rows,
                           count_put_food=32)
        self.field.update()
        self.update_iterator = UPDATE_FREQUENCY
        self.update_frequency = UPDATE_FREQUENCY
        self.clock = pygame.time.Clock()
        self.start = False
        self.next_update = True
        self.widgets = [
            Widget(x=0,
                   y=0,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Старт/Стоп',
                   background_color=BUTTON_COLOR,
                   onclick=self.start_stop,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=0,
                   y=WIDGET_HEIGHT,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Очистить',
                   onclick=self.clear,
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 2,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Размер таблицы'),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 3,
                   width=UI_WIDTH // 2,
                   height=WIDGET_HEIGHT,
                   text='-',
                   onclick=lambda: self.change_field('-'),
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=UI_WIDTH // 2,
                   y=WIDGET_HEIGHT * 3,
                   width=UI_WIDTH // 2,
                   height=WIDGET_HEIGHT,
                   text='+',
                   onclick=lambda: self.change_field('+'),
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 4,
                   width=UI_WIDTH // 2,
                   height=WIDGET_HEIGHT,
                   text='-10',
                   onclick=lambda: self.change_field('-', 10),
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=UI_WIDTH // 2,
                   y=WIDGET_HEIGHT * 4,
                   width=UI_WIDTH // 2,
                   height=WIDGET_HEIGHT,
                   text='+10',
                   onclick=lambda: self.change_field('+', 10),
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 5,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Частота обновл.'),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 6,
                   width=UI_WIDTH // 2,
                   height=WIDGET_HEIGHT,
                   text='-',
                   onclick=lambda: self.change_update_frequency('+'),
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=UI_WIDTH // 2,
                   y=WIDGET_HEIGHT * 6,
                   width=UI_WIDTH // 2,
                   height=WIDGET_HEIGHT,
                   text='+',
                   onclick=lambda: self.change_update_frequency('-'),
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 7,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Еды за раз'),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 8,
                   width=UI_WIDTH // 2,
                   height=WIDGET_HEIGHT,
                   text='-',
                   onclick=lambda: self.change_food_count('-'),
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=UI_WIDTH // 2,
                   y=WIDGET_HEIGHT * 8,
                   width=UI_WIDTH // 2,
                   height=WIDGET_HEIGHT,
                   text='+',
                   onclick=lambda: self.change_food_count('+'),
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 9,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Пищи: 1'),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 10,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Организмов: 0'),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 11,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Хищников: 0'),
            Widget(x=0,
                   y=WIDGET_HEIGHT * 12,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Поле: 36x64'),
            Widget(x=0,
                   y=resolution[1] - WIDGET_HEIGHT,
                   width=UI_WIDTH,
                   height=WIDGET_HEIGHT,
                   text='Выход',
                   background_color=BUTTON_COLOR,
                   background_color_cover=BUTTON_COVER,
                   background_color_click=BUTTON_CLICKED,
                   onclick=self.quit)
        ]

    def start_stop(self):
        if self.start:
            self.start = False
        else:
            self.start = True

    def quit(self):
        self.next_update = False

    def clear(self):
        self.field.clear()
        self.field.update()
        self.update_info()

    def change_food_count(self, action):
        if action == '+':
            self.field.count_put_food += 10
        elif action == '-':
            if self.field.count_put_food > 0:
                self.field.count_put_food -= 10

    def change_update_frequency(self, action):
        if action == '+':
            self.update_frequency += 1
            if self.update_frequency >= FPS:
                self.update_frequency = FPS
        elif action == '-':
            self.update_frequency -= 1
            if self.update_frequency <= 1:
                self.update_frequency = 1

    def change_field(self, action, n=1):
        if action == '+':
            self.rows += n
            self.cols += n
        elif action == '-':
            if self.rows > MIN_ROWS_COLS + n - 1:
                self.rows -= n
            if self.cols > MIN_ROWS_COLS + n - 1:
                self.cols -= n
        self.field = Field(self.resolution[0] - UI_WIDTH,
                           self.resolution[1],
                           self.cols,
                           self.rows,
                           count_put_food=self.field.count_put_food)
        self.field.update()

    def update_info(self):
        self.widgets[-2].text = f'Поле: {self.rows}x{self.cols}'
        self.widgets[-3].text = f'Хищников: {self.field.predators}'
        self.widgets[-4].text = f'Организмов: {self.field.organisms}'
        self.widgets[-5].text = f'Пищи: {self.field.foods}'

    def main(self):
        while True:
            if not self.update():
                break
            self.clock.tick(FPS)
        pygame.quit()

    def update(self):
        self.next_update = True
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                self.next_update = False
            elif e.type == pygame.KEYUP and e.key == pygame.K_ESCAPE:
                self.next_update = False
            elif e.type == pygame.MOUSEBUTTONUP:
                if e.button == 1:
                    pos = pygame.mouse.get_pos()
                    if pos[0] > UI_WIDTH:
                        pos = (pos[0] - UI_WIDTH, pos[1])
                        self.field.put_live(1, pos)
                        self.field.update()
                        self.update_info()

        for widget in self.widgets:
            widget.update(events)

        if self.start and not self.update_iterator:
            self.update_iterator = self.update_frequency
            self.field.update()
            self.update_info()
        if self.update_iterator:
            self.update_iterator -= 1

        self.draw()

        return self.next_update

    def draw(self):
        self.window.fill(WINDOW_BACKGROUND)
        for widget in self.widgets:
            widget.show(self.window)
        self.field.draw(self.window, (UI_WIDTH, 0))
        pygame.display.update()