MicroPython动手做(35)——体验小游戏-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

楼主: eagler8

MicroPython动手做(35)——体验小游戏

[复制链接]
 楼主| 发表于 2020-6-26 19:17 | 显示全部楼层
mPython X 实验图形编程2

02.jpg
 楼主| 发表于 2020-6-26 19:25 | 显示全部楼层
06.jpg

05.jpg
 楼主| 发表于 2020-6-26 20:20 | 显示全部楼层
11、俄罗斯方块

[mw_shl_code=arduino,true]#MicroPython动手做(35)——小游戏
#俄罗斯方块

from mpython import *
import math
import random, time

class Brick():
    def __init__(self, p_position):
        self.position = p_position

    def draw(self):

        x = self.position[1] * brick_size
        y = self.position[0] * brick_size
        oled.fill_rect(brick_size * (field_height - 1) - x, y, brick_size, brick_size, 1)


class Block():
    def __init__(self, p_bricks_layout, p_direction):
        self.bricks_layout = p_bricks_layout
        self.direction = p_direction
        self.init_position = (field_width // 2 - 2, 0)
        self.cur_layout = self.bricks_layout[self.direction]
        self.position = self.init_position
        self.stopped = False
        self.move_interval = 500
        self.last_move = 0
        self.bricks = []
        for (x, y) in self.cur_layout:
            self.bricks.append(Brick((self.position[0] + x, self.position[1] + y)))

    def draw(self):
        for brick in self.bricks:
            brick.draw()

    def isLegal(self, layout, position):
        (x0, y0) = position
        for (x, y) in layout:
            if x + x0 < 0 or y + y0 < 0 or x + x0 >= field_width or y + y0 >= field_height:
                return False
            if field_map[y + y0][x + x0] != 0:
                return False
        return True

    def left(self):
        new_position = (self.position[0] - 1, self.position[1])
        if self.isLegal(self.cur_layout, new_position):
            self.position = new_position
            self.refresh_bircks()

    def right(self):
        new_position = (self.position[0] + 1, self.position[1])
        if self.isLegal(self.cur_layout, new_position):
            self.position = new_position
            self.refresh_bircks()

    def down(self):
        (x, y) = (self.position[0], self.position[1] + 1)
        while self.isLegal(self.cur_layout, (x, y)):
            self.position = (x, y)
            self.refresh_bircks()
            y += 1

    def refresh_bircks(self):
        for (brick, (x, y)) in zip(self.bricks, self.cur_layout):
            brick.position = (self.position[0] + x, self.position[1] + y)

    def stop(self):
        global field_bricks
        global score
        self.stopped = True
        ys = []
        for brick in self.bricks:
            field_bricks.append(brick)
            (x, y) = brick.position
            if y not in ys:
                ys.append(y)
            field_map[y][x] = 1

        eliminate_count = 0
        ys.sort()

        for y in ys:
            if 0 in field_map[y]:
                continue
            eliminate_count += 1
            for fy in range(y, 0, -1):
                field_map[fy] = field_map[fy - 1][:]
            field_map[0] = [0 for i in range(field_width)]

            tmp_field_bricks = []
            for fb in field_bricks:
                (fx, fy) = fb.position
                if fy < y:
                    fb.position = (fx, fy + 1)
                    tmp_field_bricks.append(fb)
                elif fy > y:
                    tmp_field_bricks.append(fb)
            field_bricks = tmp_field_bricks
        if eliminate_count == 1:
            score += 1
        elif eliminate_count == 2:
            score += 2
        elif eliminate_count == 3:
            score += 4
        elif eliminate_count == 4:
            score += 6

    def update(self, time):
        self.draw()
        if time - self.last_move >= self.move_interval:
            new_position = (self.position[0], self.position[1] + 1)
            if self.isLegal(self.cur_layout, new_position):
                self.position = new_position
                self.refresh_bircks()
                self.last_move = time
            else:
                self.stop()

    def rotate(self):
        new_direction = (self.direction + 1) % len(self.bricks_layout)
        new_layout = self.bricks_layout[new_direction]
        if not self.isLegal(new_layout, self.position):
            return
        self.direction = new_direction
        self.cur_layout = new_layout
        for (brick, (x, y)) in zip(self.bricks, self.cur_layout):
            brick.position = (self.position[0] + x, self.position[1] + y)
        self.refresh_bircks()
        self.draw()


# 0: oooo
# 1: oo
#    oo
# 2: o
#   ooo
# 3: o
#    oo
#     o
# 4:  o
#    oo
#    o
# 5: ooo
#    o
# 6: ooo
#      o
bricks_layout_0 = (((0, 0), (0, 1), (0, 2), (0, 3)), ((0, 1), (1, 1), (2, 1), (3, 1)))
bricks_layout_1 = (((1, 0), (2, 0), (1, 1), (2, 1)), )
bricks_layout_2 = (
    ((1, 0), (0, 1), (1, 1), (2, 1)),
    ((0, 1), (1, 0), (1, 1), (1, 2)),
    ((1, 2), (0, 1), (1, 1), (2, 1)),
    ((2, 1), (1, 0), (1, 1), (1, 2)),
)
bricks_layout_3 = (
    ((0, 1), (1, 1), (1, 0), (2, 0)),
    ((0, 0), (0, 1), (1, 1), (1, 2)),
)
bricks_layout_4 = (
    ((0, 0), (1, 0), (1, 1), (2, 1)),
    ((1, 0), (1, 1), (0, 1), (0, 2)),
)
bricks_layout_5 = (
    ((0, 0), (1, 0), (1, 1), (1, 2)),
    ((0, 2), (0, 1), (1, 1), (2, 1)),
    ((1, 0), (1, 1), (1, 2), (2, 2)),
    ((2, 0), (2, 1), (1, 1), (0, 1)),
)
bricks_layout_6 = (
    ((2, 0), (1, 0), (1, 1), (1, 2)),
    ((0, 0), (0, 1), (1, 1), (2, 1)),
    ((0, 2), (1, 2), (1, 1), (1, 0)),
    ((2, 2), (2, 1), (1, 1), (0, 1)),
)

field_width, field_height = 16, 30
brick_size = 4
field_map = [[0 for i in range(field_width)] for i in range(field_height)]
field_bricks = []
score = 0
running = True
threshhold = 400


def drawField():
    for brick in field_bricks:
        brick.draw()


def getBlock():
    block_type = random.randint(0, 6)
    if block_type == 0:
        return Block(bricks_layout_0, random.randint(0, len(bricks_layout_0) - 1))
    elif block_type == 1:
        return Block(bricks_layout_1, random.randint(0, len(bricks_layout_1) - 1))
    elif block_type == 2:
        return Block(bricks_layout_2, random.randint(0, len(bricks_layout_2) - 1))
    elif block_type == 3:
        return Block(bricks_layout_3, random.randint(0, len(bricks_layout_3) - 1))
    elif block_type == 4:
        return Block(bricks_layout_4, random.randint(0, len(bricks_layout_4) - 1))
    elif block_type == 5:
        return Block(bricks_layout_5, random.randint(0, len(bricks_layout_5) - 1))
    elif block_type == 6:
        return Block(bricks_layout_6, random.randint(0, len(bricks_layout_6) - 1))


def run():
    global running
    btn_n_stat, btn_o_stat, btn_t_stat, btn_p_stat = [0] * 4

    while running:

        cur_block = getBlock()

        if not cur_block.isLegal(cur_block.cur_layout, cur_block.position):
            cur_block.draw()
            running = False
            continue

        while not cur_block.stopped:

            oled.fill(0)
            ticks = time.ticks_ms()
            cur_block.update(ticks)
            drawField()
            oled.show()

            if touchPad_T.read() < threshhold and btn_t_stat == 0:
                cur_block.rotate()
                btn_t_stat = 1
            elif touchPad_T.read() >= threshhold:
                btn_t_stat = 0

            if touchPad_P.read() < threshhold and btn_p_stat == 0:
                cur_block.down()
                btn_p_stat = 1
            elif touchPad_P.read() >= threshhold:
                btn_p_stat = 0

            if touchPad_N.read() < threshhold and btn_n_stat == 0:
                cur_block.left()
                btn_n_stat = 1
            elif touchPad_N.read() >= threshhold:
                btn_n_stat = 0

            if touchPad_O.read() < threshhold and btn_o_stat == 0:
                cur_block.right()
                btn_o_stat = 1
            elif touchPad_O.read() >= threshhold:
                btn_o_stat = 0
    oled.fill(0)
    oled.text('Game over!', 25, 20)
    oled.text('Score:%d' % score, 25, 32)
    oled.show()


if __name__ == '__main__':
    run()[/mw_shl_code]
 楼主| 发表于 2020-6-26 20:47 | 显示全部楼层
1593174938092.gif
 楼主| 发表于 2020-6-27 08:13 | 显示全部楼层
12、 乒乓球


[mw_shl_code=arduino,true]#MicroPython动手做(35)——小游戏
# 乒乓球

from mpython import *
import music


class Pong():
    def __init__(self):

        self.running = True
        self.start = False
        self.ball_rad = 5
        self.bats_position = 0
        self.bats_width = 15
        self.bats_height = 4

        self.ball_x = self.bats_width // 2
        self.ball_y = 64 - (self.ball_rad + self.bats_height + 1)
        self.inc_x, self.inc_y = 1, 1
        self.score = 0

    def collision(self):

        if self.ball_x >= 128 - self.ball_rad or self.ball_x < self.ball_rad:
            self.inc_x = -self.inc_x
        if self.ball_y >= 64 - (self.ball_rad + self.bats_height) or self.ball_y <= self.ball_rad:
            self.inc_y = -self.inc_y

    def update(self):
        self.ball_x = self.ball_x + self.inc_x
        self.ball_y = self.ball_y + self.inc_y
        self.bats_position = min(max(self.bats_position, 0), 128 - self.bats_width)

    def is_hit(self):
        # print('ball:', self.ball_x, self.ball_y, 'bats:', self.bats_position)
        if self.ball_y >= 64 - (self.ball_rad + self.bats_height):
            if self.ball_x >= self.bats_position + self.bats_width + self.ball_rad or self.ball_x <= self.bats_position - self.ball_rad:

                return False
            self.score += 1
            return True

    def run(self):

        while self.running:
            if button_a.value() == 0 and button_b.value() == 1:
                self.bats_position -= 2
                self.start = True
            if button_a.value() == 1 and button_b.value() == 0:
                self.bats_position += 2
                self.start = True

            if self.start:
                self.update()
                self.collision()

                if self.is_hit() == False:
                    self.running = False
                    continue

            oled.fill(0)
            oled.fill_circle(self.ball_x, self.ball_y, self.ball_rad, 1)
            oled.fill_rect(self.bats_position, 64 - self.bats_height, self.bats_width, self.bats_height, 1)
            oled.show()

        oled.text('Game over!', 20, 20)
        oled.text('Score %d' % self.score, 20, 32)
        oled.show()


if __name__ == '__main__':
    pong = Pong()
    pong.run()[/mw_shl_code]
 楼主| 发表于 2020-6-27 08:34 | 显示全部楼层
#MicroPython动手做(35)——小游戏
# 乒乓球(实验视频)

https://v.youku.com/v_show/id_XN ... oneSokuUgc_1.dtitle

52.jpg

 楼主| 发表于 2020-6-27 08:41 | 显示全部楼层

13、飞行小鸟

[mw_shl_code=arduino,true]#MicroPython动手做(35)——小游戏
#飞行小鸟

from mpython import *
from framebuf import FrameBuffer
import framebuf
import time, uos,urandom

# 16 x 12
BIRD = bytearray([
    0x7, 0xe0, 0x18, 0xf0, 0x21, 0xf8, 0x71, 0xec, 0xf9, 0xec, 0xfc, 0xfc, 0xbe, 0x7e, 0x4c, 0x81, 0x71, 0x7e, 0x40,
    0x82, 0x30, 0x7c, 0xf, 0x80
])

# 16 x 32
PIPE_TOP = bytearray([
    0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
    0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c,
    0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0xff, 0xff, 0x80, 0xf, 0x80,
    0xf, 0x80, 0xf, 0x80, 0xf, 0xff, 0xff
])
PIPE_DOWN = bytearray([
    0xff, 0xff, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0xff, 0xff, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c,
    0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
    0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c,
    0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c
])


# Bitmap images
bird_size = (16, 12)
pipe_size = (16, 32)


WIDTH = 128
HEIGHT = 64


"""飞行小鸟类"""
class Bird:
    def __init__(self):
        self.height = bird_size[1]
        self.y = HEIGHT // 2 - self.height // 2
        self.wing_power = 4
        self.gravity = 0.8
        self.vel = -self.wing_power

    # 下落
    def drop(self):
        self.vel += self.gravity
        self.y = int(self.y + self.vel)

    # 飞行
    def flap(self):
        self.vel = -self.wing_power

    # 是否坠落
    def crashed(self):                          
        y_limit = HEIGHT - self.height
        return self.y > y_limit

"""障碍类"""
class Obstacle:
    def __init__(self, x,size ):
        self.size =size
        self.gap = urandom.randint(6 + self.size, HEIGHT - 6 - self.size)     # 随机生成间隙大小
        self.x = x              # 距离鸟大小
        self.score = 0          # 分数
        self.rate = 3           # 速率

    # 移动
    def scroll(self):           
        self.x -= self.rate   
        if self.x < -pipe_size[0]:
            self.score += 1
            self.x = WIDTH
            self.gap = urandom.randint(6 + self.size, HEIGHT - 6 - self.size)

    # 是否碰撞
    def collided(self, y):                     
        if self.x < bird_size[0] and self.x > -pipe_size[0] and \
           (self.gap - y > self.size or y + bird_size[1] - self.gap > self.size):
            return True
        else:
            return False


class Game():
    def __init__(self,gap_size):
        
        # 创建鸟和管道的framebuffer
        self.bird_fb = FrameBuffer(BIRD, bird_size[0], bird_size[1], framebuf.MONO_HLSB)         
        self.pipe_top_fb = FrameBuffer(PIPE_TOP, pipe_size[0], pipe_size[1], framebuf.MONO_HLSB)
        self.pipe_down_fb = FrameBuffer(PIPE_DOWN, pipe_size[0], pipe_size[1], framebuf.MONO_HLSB)

        self.gap_size = gap_size
        self.high_score = 0
        self.pressed  = False
        self.game_state = 0
        self.flappy_bird =  None
        self.obstacle_1 =  None
        self.obstacle_2 =  None

    # 保存最高分
    def write_high_score(self,n):
        f = open('fb_high_score.txt', 'w')
        f.write(str(n))
        f.close()

    # 读取最高分
    def read_high_score(self):
        if 'fb_high_score' in uos.listdir():
            f = open('fb_high_score.txt', 'r')
            high_score = f.read()
            f.close()
            return int(high_score)
        else:
            self.write_high_score(0)
            return 0

   # 绘制
    def draw(self):
        oled.fill(0)
        oled.blit(self.bird_fb, 0, self.flappy_bird.y)
        oled.blit(self.pipe_top_fb, self.obstacle_1.x, self.obstacle_1.gap - self.gap_size - pipe_size[1])
        oled.blit(self.pipe_down_fb, self.obstacle_1.x, self.obstacle_1.gap + self.gap_size)
        oled.blit(self.pipe_top_fb, self.obstacle_2.x, self.obstacle_2.gap - self.gap_size - pipe_size[1])
        oled.blit(self.pipe_down_fb, self.obstacle_2.x, self.obstacle_2.gap + self.gap_size)
        oled.fill_rect(WIDTH // 2 - 13, 0, 26, 9, 0)
        oled.text('%03d' % (self.obstacle_1.score + self.obstacle_2.score), WIDTH // 2 - 12, 0)
        oled.show()
   

    def _clicked(self):
        if button_a.value() == 0 and not self.pressed:
            self.pressed = True
            return True
        elif button_a.value() == 1 and self.pressed:
            self.pressed = False
        return False

    # 开机画面
    def game_start(self):
        oled.fill(0)
        oled.blit(self.pipe_down_fb, (WIDTH - pipe_size[0]) // 2, HEIGHT - 12)
        oled.blit(self.bird_fb, (WIDTH - bird_size[0]) // 2, HEIGHT - 12 - bird_size[1])
        oled.rect(0, 0, WIDTH, HEIGHT, 1)
        oled.text('F L A P P Y', WIDTH // 2 - 44, 3)
        oled.text('B I R D', WIDTH // 2 - 28, 13)
        oled.text('Record: ' + '%03d' % self.high_score, WIDTH // 2 - 44, HEIGHT // 2 - 6)
        oled.show()
        self.game_state = 1
      
    def game_waiting(self):
        if self._clicked():
            self.flappy_bird = Bird()                                                               # 实例小鸟对象
            self.obstacle_1 = Obstacle(WIDTH,self.gap_size)                                           # 实例第一个障碍对象
            self.obstacle_2 = Obstacle(WIDTH + (WIDTH + pipe_size[0]) // 2,self.gap_size)             # 实例第二个障碍对象
            self.game_state = 2

    def game_running(self):
        if self._clicked():
            self.flappy_bird.flap()
        self.flappy_bird.drop()
        if self.flappy_bird.crashed():
            self.flappy_bird.y = HEIGHT - self.flappy_bird.height      # 边界限制
            self.game_state = 3
        self.obstacle_1.scroll()
        self.obstacle_2.scroll()
        if self.obstacle_1.collided(self.flappy_bird.y) or self.obstacle_2.collided(self.flappy_bird.y):
            self.game_state = 3
        self.draw()

    def game_over(self):
        oled.fill_rect(WIDTH // 2 - 32, 10, 64, 23, 0)
        oled.rect(WIDTH // 2 - 32, 10, 64, 23, 1)
        oled.text('G A M E', WIDTH // 2 - 28, 13)
        oled.text('O V E R', WIDTH // 2 - 28, 23)
        self.score = self.obstacle_1.score + self.obstacle_2.score
        if self.score > self.high_score:
            self.high_score = self.score
            oled.fill_rect(WIDTH // 2 - 48, 37, 96, 14, 0)
            oled.rect(WIDTH // 2 - 48, 37, 96, 14, 1)
            oled.text('New record!', WIDTH // 2 - 44, 40)
            self.write_high_score(self.high_score)
        oled.show()

        try:
            self.send_score(self.score)
        except:
            pass
        self.game_state = 1


    def run(self):
        while True:
            if self.game_state == 0: self.game_start()
            elif self.game_state == 1: self.game_waiting()
            elif self.game_state == 2: self.game_running()
            elif self.game_state == 3: self.game_over()



if __name__ == '__main__':
    game=Game(gap_size = 16)
    game.run()[/mw_shl_code]
 楼主| 发表于 2020-6-27 09:42 | 显示全部楼层
57.gif
 楼主| 发表于 2020-6-28 12:29 | 显示全部楼层
14、打砖块(大于)


[mw_shl_code=arduino,true]#MicroPython动手做(35)——小游戏
#打砖块

import time
import random
from mpython import *

random.seed(time.ticks_cpu())


my_listy = []
my_listx = []
m = 0
n = 0
score = 0
x = random.randint(35, 90)
y = 60
cx = 1
cy = -1
Lx = 50
for count in range(3):
    m = 0
    for count in range(16):
        my_listx.append(m)
        m = m + 8
n = 0
for count in range(3):
    for count in range(16):
        my_listy.append(n)
    n = n + 8
while True:
    m = 0
    n = 0
    oled.fill(0)
    for count in range(48):
        oled.rect(my_listx[m], my_listy[n], 8, 8, 1)
        if y <= my_listy[n] + 10:
            if x >= my_listx[m] and x <= my_listx[m] + 8:
                my_listx[m] = (-40)
                my_listy[n] = (-40)
                cy = 1
                score = score + 1
        m = m + 1
        n = n + 1
    oled.fill_rect(Lx, 62, 30, 2, 1)
    oled.circle(x, y, 3, 1)
    oled.show()
    if button_a.value() == 0:
        Lx = Lx + -3
        if Lx <= 0:
            Lx = 0
    if button_b.value() == 0:
        Lx = Lx + 3
        if Lx >= 107:
            Lx = 107
    x = x + cx
    y = y + cy
    if x <= 2:
        cx = 1
    if x >= 125:
        cx = -1
    if y <= 2:
        cy = 1
    if y > 60:
        if x >= Lx - 2 and x <= Lx + 32:
            cy = -1
        else:
            oled.fill(0)
            oled.DispChar(str("游戏结束,得分为:") + str(score), 0, 16, 1)
            oled.show()
            break[/mw_shl_code]
 楼主| 发表于 2020-6-28 12:31 | 显示全部楼层
mPython X 实验图形编程

01.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-28 01:41 , Processed in 0.082069 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表