兔年首文迎新春-Cesium橘子洲烟花礼赞

Posted 夜郎king

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了兔年首文迎新春-Cesium橘子洲烟花礼赞相关的知识,希望对你有一定的参考价值。

兔年新春

今天是兔年大年初二,神州大地,在经历了疫情的三年后迎来开放的一个春节。大家都沉浸在欢乐幸福的春节气氛中。玉兔迎新春,祝福齐送到:白兔祝你身体安康,黑兔祝你薪水高涨,灰兔送你梦想如意,花兔愿你早日高升,公兔祈祷你名利双收,母兔称赞你家和万事兴,只有兔崽崽最淘气,鞭炮连连,让你欢乐一整年。祝各位技术同仁在新的一年里,发量比Bug多,他/她比最帅/最靓的明星更亮,RMB把钱包撑破。

一、橘子洲头

1、橘子洲与伟人

大家对《沁园春.长沙》想必都非常熟悉。词的内容,上阙为描写湘江、橘子洲、岳簏山生机盎然的秋景,下阙为怀念同学少年的生活,抒发救世济民的远大理想,洋溢着激流奋进的壮志和豪情。现在,诗词碑已成为橘洲景区的标志性景点之一。词中,橘子洲头、看万山红遍、层林尽染、万江碧透、百舸争流,描述的就是橘子洲头的景象。恰同学少年,风华正茂,书生意气,挥斥方遒。表达了伟人当时的远大理想和壮志豪情,每次登临岳麓山,到岳麓书院,于橘子洲头,感受到流传下来的气魄,因此,这山和水也便被赋予了精神。

2、橘子洲与烟花

作为旅游城市,橘子洲的烟花表演一直是以前很多来星城必须要进行的一项打卡活动,同时也是湖南烟花对外展示的一个窗口。当然,烟花燃放的污染物排放一直是人们关注的首个重点目标,而现在浏阳烟花也是不断的改进烟花燃放工艺,争取减少污染区的排放。而随着疫情的爆发,也加上对排污治理的整治,橘子洲烟花与人们的邂逅机会就越来越少,曾几何时,橘子洲烟花是一周一次,后面变成了逢重大活动才燃放,一般在一年4次左右。下面来几张曾经的橘子洲烟花的燃放盛况,供大家观赏吧,图片来源于网络供图(百家号影像湖南)。

3、绿色燃放

虽然现在难得遇到一次橘子洲头的烟花燃放,但作为技术人,可以充分利用WebGL技术,结合时空地理地图,地形数据来一场实时可见的烟花燃放盛况。在这里遇见岳麓山、遇见橘子洲头,山水洲城的盛宴。在本文中基于Cesium开源框架,采用开源WebGL技术,叠加全国影像地图(本地私有化),标签路网数据、地形数据,采用粒子系统,实现烟花燃放的效果。先来一张效果图开胃吧。

二、Cesium烟花实现

1、相关依赖

由于采用Cesium开源实现,因此基础的依赖于Cesium.js,感兴趣的朋友可以自行在github(cesium github)或者官方网站(cesium)上下载相关依赖。Cesium可以基于原生的html5和javascript来进行运行,也支持和现代流程框架React和Vue等前端框架进行集成开发。可以根据自己的技术栈来合理选型。

将下载之后的Cesium编译后的js文件复制到工程的Build目录下,如下所示:

在上一层的Documentation目录中是同版本对应的API文档,您可以直接打开html页面,这是最全的API介绍文档。

2、新建html页面

在cesiumdemo或者任意目录下新建fireworks2.html,关键代码如下所示:

<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Use correct character set. -->
    <meta charset="utf-8" />
    <!-- Tell IE to use the latest, best version. -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <title>大展宏兔,大吉大利</title>
    <script src="Build/Cesium/Cesium.js"></script>
    <style>
      @import url(Build/Cesium/Widgets/widgets.css);
      html,
      body,
      #cesiumContainer 
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
      
    </style>
  </head>
  <body>
    <div id="cesiumContainer"></div>
  </body>
</html>

在上面的代码中通过引入Cesium.js,并且在页面中创建了一个div用于渲染展示cesium地球组件。但这是还未将cesium和页面元素进行绑定,也没有加载加载相应的底图和地形数据。

3、底图和地形数据加载

下面将通过UrlTemplateImageryProvider对象来进行Cesium的底图对象定义,示例代如下所示:

//加载影像底图
var imageryProvider = new Cesium.UrlTemplateImageryProvider(
    url: "http://localhost:8086/data/basemap_water/z/x/y.png",
    tilingScheme: new Cesium.WebMercatorTilingScheme(),
    fileExtension: 'png',
    minimumLevel: 1,
    maximumLevel: 16
);

var labelProvider = new Cesium.UrlTemplateImageryProvider(
    url: "http://localhost:8086/data/basemap_nowater/1-10label/z/x/y.png",
    tilingScheme: new Cesium.GeographicTilingScheme(),//投影方式为经纬度直投,否则路网不对
    fileExtension: 'png',
    minimumLevel: 1,
    maximumLevel: 10
 );
//加载本地地形数据
var terrainLayer = new Cesium.CesiumTerrainProvider(
    url: "http://localhost:8086/data/hunanterrain",
    // 请求照明
    requestVertexNormals: true,
    // 请求水波纹效果
    requestWaterMask: false
);

上面的代码定义了地形数据,同时使用如下的代码将地形数据、底图数据都添加到Cesium的视图对象中,并且将标签图层也添加到对象中。用于系统,同时将cesium的展示视角初始调整为橘子洲的经纬度坐标。

var viewer = new Cesium.Viewer('cesiumContainer',
    imageryProvider:imageryProvider,
    terrainProvider: terrainLayer,
    baseLayerPicker:false,
    homeButton: true,
    baseLayerPicker: false,
    animation: false,
    timeline: false,
    navigationHelpButton: false,
    geocoder: false,
    sceneModePicker: false,
    shouldAnimate: true,
);

// 设置相机初始位置
var homeCameraView = 
        destination: Cesium.Cartesian3.fromDegrees(112.955074,28.16843,507.0480578185452),
            orientation: 
                heading:5.656571359006588,
                pitch: -0.28428181994862656,
                roll: 0
            ,
        ;

viewer.camera.setView(homeCameraView);

viewer.imageryLayers.addImageryProvider(labelProvider);
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none";

viewer.scene.globe.enableLighting = false;//关闭光照

4、粒子系统

粒子系统是WebGL中的一个非常重要的组成部分,通过粒子系统可以实现很多的特效。粒子系统是一种模拟复杂物理效应的图形技术。粒子系统是小图片的集合,当放到一起观察它们时,会形成一个更复杂的“模糊”对象,例如火、烟雾、气候,或者烟火(fireworks)。通过使用例如初始位置、速度和寿命属性来指定单个粒子的行为,可以控制这些复杂的效果。这里推荐一篇介绍粒子系统比较简单同时讲解比较清楚的入门博客Cesium中文教程-粒子系统介绍(Introduction to Particle Systems)cesium粒子系统介绍,更多的关于粒子系统的说明,可以上WebGL知识去深入学习,这里不做特别深入的讲解(因为博主也学得不深)。本文结合代码来简要说明粒子系统的一些知识。

模拟图片源,粒子系统可以理解是多个小图片的集合整体渲染。所以可以基于外部图片的渲染,比如爆炸的效果,同时作为烟花的特效,这里采用模拟图片实现。关键代码如下:

let particleCanvas;

function getImage() 
  if (!Cesium.defined(particleCanvas)) 
        particleCanvas = document.createElement("canvas");
        particleCanvas.width = 30;
        particleCanvas.height = 30;
        const context2D = particleCanvas.getContext("2d");
        context2D.beginPath();
        context2D.arc(10, 10, 10, 0, Cesium.Math.TWO_PI, true);
        context2D.closePath();
        context2D.fillStyle = "rgb(255, 255, 255)";
        context2D.fill();
       
   return particleCanvas;

粒子系统在Cesium被进行了简单封装,开发者通过API进行简单调用即可。

new Cesium.ParticleSystem(
    image: getImage(),
    startColor: color,
    endColor: color.withAlpha(0.0),
    particleLife: life,
    speed: 30.0,
    imageSize: particlePixelSize,
    emissionRate: 0,
    emitter: new Cesium.SphereEmitter(1.8),
    bursts: bursts,
    lifetime: lifetime,
    updateCallback: force,
    modelMatrix: modelMatrix,
    emitterModelMatrix: emitterModelMatrix,
   )
);

最后通过循环和一些随机坐标偏移来实现烟花的位置随机展示,在粒子播放的时候,会进行回归调用。

const xMin = -100.0;
const xMax = 150.0;
const yMin = -80.0;
const yMax = 150.0;
const zMin = -50.0;
const zMax = 50.0;

const colorOptions = [

minimumRed: 0.75,
green: 0.0,
minimumBlue: 0.8,
alpha: 1.0,
,

red: 0.0,
minimumGreen: 0.75,
minimumBlue: 0.8,
alpha: 1.0,
,

red: 0.0,
green: 0.0,
minimumBlue: 0.8,
alpha: 1.0,
,

minimumRed: 0.75,
minimumGreen: 0.75,
blue: 0.0,
alpha: 1.0,
,
];

for (let i = 0; i < numberOfFireworks; ++i) 
     const x = Cesium.Math.randomBetween(xMin, xMax);
     const y = Cesium.Math.randomBetween(yMin, yMax);
     const z = Cesium.Math.randomBetween(zMin, zMax);
     const offset = new Cesium.Cartesian3(x, y, z);
     const color = Cesium.Color.fromRandom(
          colorOptions[i % colorOptions.length]
     );

      const bursts = [];
      for (let j = 0; j < 5; ++j) 
            bursts.push(
              new Cesium.ParticleBurst(
                time: Cesium.Math.nextRandomNumber() * lifetime,
                minimum: burstSize,
                maximum: burstSize,
              )
            );
      

    createFirework(offset, color, bursts);

下面给一个最终的效果图,一个在橘子洲头的动态烟花效果,真诚的祝福大家新年快乐,兔年大吉。

5、粒子系统加载

这里给的Cesium.js是编译之后的,所以对于debug不太友好,如果需要源码调试可以使用开发版本,可以观察到更深入的调用过程。对于理解粒子系统更加有帮助,调试起来吧。

总结

以上就是本文的所有内容,本文首先介绍了橘子洲头的一些相关知识,它与伟人的渊源,与烟花的关系。最主要的是介绍了基于Cesium的电子烟花的展示播放技术,重点介绍了在Cesium中如何进行集成,粒子系统的创建过程以及加载技术。最后祝所有的技术人都能一飞冲天,炫彩夺目。

Python小游戏2023兔年吉祥,祝大家辞旧迎新,前兔无量啦~兔年都在玩的这两款游戏,只有0.1%的人通关,你玩了吗?(内含福利源码)

前言

HAPPY NEW YEAR——2023🐇年吉祥☀

🌙🌙🌙🌙🌙🌙除夕辞旧迎新🌙🌙🌙🌙🌙🌙

++ 新年快乐 钱🐇无量 ++

所有文章完整的素材+源码都在👇👇

粉丝白嫖源码福利,请移步至CSDN社区或文末公众hao即可免费。

当和家人围坐一席、觥筹交错举杯庆祝时,就轮到要说祝福语了~~

这时的你,是不是经常大脑一片空白?只能从嘴里蹦出为数不多的几个字:吃好喝好!

PS:兔年祝福——含“兔”的四字词语

大展宏“兔” 前“兔”似锦——“兔”步青云 前“兔”无量

“兔”然暴富 “兔”来运转——扬眉“兔”气 “兔”飞猛进

奋发“兔”强 钱“兔”无忧——全新“兔”破 谈“兔”不凡

“兔”出贡献 好事成“兔”——金兔送福 兔年大吉

今天来给大家来两款Python适合兔年玩儿的小游戏——《前途似锦消消消》寓意前路坦荡,更

上一层楼哦;另一款《兔年吉祥拼拼拼》寓意2023年心想事成,所愿皆成真!

正文

Hi,兄弟姐妹们好,我是栗子~

新年新气象!咱们不仅要自己穿得漂亮,也得给手机来个新壁纸!这两天我在网上冲浪的时

候,发现各种新年壁纸真的是绝绝子。

所以,今天木子就给你们整理了超多张「新年壁纸」,做微信聊天背景也超赞!还不赶紧来get

~(仅几张展示,大部分的可以找我拿蛮,毕竟文章内容主次还是要分清滴 哈哈)

在写代码之前插播几张新年壁纸,嘿嘿,希望大家喜欢啦💌💌

一、《前途似锦消消消》Pygame游戏代码

1)🐰新年祝福壁纸✨

👆过年嘛,那自然是要讨句吉祥话,这样新的一年才能红红火火!

👆姐妹们记得把闺蜜&男朋友薅出来一起换壁纸呀!

👆春联和福字除了贴在家里,当然也能贴在手机上哦~

2)开发环境

小编使用的环境:Python3、Pycharm社区版、pygame模块需要安装,其他自带的模块就不

一一 展示啦。

 镜像源方法—模块安装:pip install -i https://pypi.douban.com/simple/+模块名 

3)代码展示

主程序:

import os
import sys
import cfg
import pygame
from modules import *


'''游戏主程序'''
def main():
    pygame.init()
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.display.set_caption('前兔似锦消消消🥕🥕')
    # 加载背景音乐
    pygame.mixer.init()
    pygame.mixer.music.load(os.path.join(cfg.ROOTDIR, "resources/audios/bg.mp3"))
    pygame.mixer.music.set_volume(0.6)
    pygame.mixer.music.play(-1)
    # 加载音效
    sounds = 
    sounds['mismatch'] = pygame.mixer.Sound(os.path.join(cfg.ROOTDIR, 'resources/audios/badswap.wav'))
    sounds['match'] = []
    for i in range(6):
        sounds['match'].append(pygame.mixer.Sound(os.path.join(cfg.ROOTDIR, 'resources/audios/match%s.wav' % i)))
    # 加载字体
    font = pygame.font.Font(os.path.join(cfg.ROOTDIR, 'resources/font/font.TTF'), 25)
    # 图片加载
    gem_imgs = []
    for i in range(1, 8):
        gem_imgs.append(os.path.join(cfg.ROOTDIR, 'resources/images/gem%s.png' % i))
    # 主循环
    game = gemGame(screen, sounds, font, gem_imgs, cfg)
    while True:
        score = game.start()
        flag = False
        # 一轮游戏结束后玩家选择重玩或者退出
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE):
                    pygame.quit()
                    sys.exit()
                elif event.type == pygame.KEYUP and event.key == pygame.K_r:
                    flag = True
            if flag:
                break
            screen.fill((135, 206, 235))
            text0 = 'Final score: %s' % score
            text1 = 'Press <R> to restart the game.'
            text2 = 'Press <Esc> to quit the game.'
            y = 150
            for idx, text in enumerate([text0, text1, text2]):
                text_render = font.render(text, 1, (85, 65, 0))
                rect = text_render.get_rect()
                if idx == 0:
                    rect.left, rect.top = (212, y)
                elif idx == 1:
                    rect.left, rect.top = (122.5, y)
                else:
                    rect.left, rect.top = (126.5, y)
                y += 100
                screen.blit(text_render, rect)
            pygame.display.update()
        game.reset()


'''run'''
if __name__ == '__main__':
    main()

4)效果展示

🐇这么多的兔兔,有没有感觉头开始晕起来了,2333

不知道你怎么样了。反正我是玩儿的时候脑瓜子嗡嗡的!

二、《兔年吉祥拼拼拼》Pygame游戏代码

1)🐰治愈系兔兔壁纸✨

👇新的一年要前途无量呀~

每年年初都是大家立flag的时候,虽然大概也许并不能达成,但至少换个壁纸以表决心!

2)开发环境

小编使用的环境:Python3、Pycharm社区版、pygame模块需要安装,其他自带的模块就不

一一 展示啦。

 镜像源方法—模块安装:pip install -i https://pypi.douban.com/simple/+模块名 

3)代码展示

主程序:

import os
import sys
import cfg
import random
import pygame


'''判断游戏是否结束'''
def isGameOver(board, size):
    assert isinstance(size, int)
    num_cells = size * size
    for i in range(num_cells-1):
        if board[i] != i: return False
    return True


'''将空白Cell左边的Cell右移到空白Cell位置'''
def moveR(board, blank_cell_idx, num_cols):
    if blank_cell_idx % num_cols == 0: return blank_cell_idx
    board[blank_cell_idx-1], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx-1]
    return blank_cell_idx - 1


'''将空白Cell右边的Cell左移到空白Cell位置'''
def moveL(board, blank_cell_idx, num_cols):
    if (blank_cell_idx+1) % num_cols == 0: return blank_cell_idx
    board[blank_cell_idx+1], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx+1]
    return blank_cell_idx + 1


'''将空白Cell上边的Cell下移到空白Cell位置'''
def moveD(board, blank_cell_idx, num_cols):
    if blank_cell_idx < num_cols: return blank_cell_idx
    board[blank_cell_idx-num_cols], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx-num_cols]
    return blank_cell_idx - num_cols


'''将空白Cell下边的Cell上移到空白Cell位置'''
def moveU(board, blank_cell_idx, num_rows, num_cols):
    if blank_cell_idx >= (num_rows-1) * num_cols: return blank_cell_idx
    board[blank_cell_idx+num_cols], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx+num_cols]
    return blank_cell_idx + num_cols


'''获得打乱的拼图'''
def CreateBoard(num_rows, num_cols, num_cells):
    board = []
    for i in range(num_cells): board.append(i)
    # 去掉右下角那块
    blank_cell_idx = num_cells - 1
    board[blank_cell_idx] = -1
    for i in range(cfg.NUMRANDOM):
        # 0: left, 1: right, 2: up, 3: down
        direction = random.randint(0, 3)
        if direction == 0: blank_cell_idx = moveL(board, blank_cell_idx, num_cols)
        elif direction == 1: blank_cell_idx = moveR(board, blank_cell_idx, num_cols)
        elif direction == 2: blank_cell_idx = moveU(board, blank_cell_idx, num_rows, num_cols)
        elif direction == 3: blank_cell_idx = moveD(board, blank_cell_idx, num_cols)
    return board, blank_cell_idx


'''随机选取一张图片'''
def GetImagePath(rootdir):
    imagenames = os.listdir(rootdir)
    assert len(imagenames) > 0
    return os.path.join(rootdir, random.choice(imagenames))


'''显示游戏结束界面'''
def ShowEndInterface(screen, width, height):
    screen.fill(cfg.BACKGROUNDCOLOR)
    font = pygame.font.Font(cfg.FONTPATH, width//15)
    title = font.render('恭喜! 你成功完成了拼图!', True, (233, 150, 122))
    rect = title.get_rect()
    rect.midtop = (width/2, height/2.5)
    screen.blit(title, rect)
    pygame.display.update()
    while True:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                pygame.quit()
                sys.exit()
        pygame.display.update()


'''显示游戏开始界面'''
def ShowStartInterface(screen, width, height):
    screen.fill(cfg.BACKGROUNDCOLOR)
    tfont = pygame.font.Font(cfg.FONTPATH, width//4)
    cfont = pygame.font.Font(cfg.FONTPATH, width//20)
    title = tfont.render('兔年吉祥', True, cfg.RED)
    content1 = cfont.render('前兔似锦,大展宏兔', True, cfg.BLUE)
    content2 = cfont.render('按H、M、L开始游戏', True, cfg.BLUE)
    trect = title.get_rect()
    trect.midtop = (width/2, height/10)
    crect1 = content1.get_rect()
    crect1.midtop = (width/2, height/2.2)
    crect2 = content2.get_rect()
    crect2.midtop = (width/2, height/1.8)
    screen.blit(title, trect)
    screen.blit(content1, crect1)
    screen.blit(content2, crect2)
    while True:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == ord('l'): return 3
                elif event.key == ord('m'): return 4
                elif event.key == ord('h'): return 5
        pygame.display.update()


'''主函数'''
def main():
    # 初始化
    pygame.init()
    clock = pygame.time.Clock()
    # 加载图片
    game_img_used = pygame.image.load(GetImagePath(cfg.PICTURE_ROOT_DIR))
    game_img_used = pygame.transform.scale(game_img_used, cfg.SCREENSIZE)
    game_img_used_rect = game_img_used.get_rect()
    # 设置窗口
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.display.set_caption('兔年吉祥小游戏')
    # 游戏开始界面
    size = ShowStartInterface(screen, game_img_used_rect.width, game_img_used_rect.height)
    assert isinstance(size, int)
    num_rows, num_cols = size, size
    num_cells = size * size
    # 计算Cell大小
    cell_width = game_img_used_rect.width // num_cols
    cell_height = game_img_used_rect.height // num_rows
    # 避免初始化为原图
    while True:
        game_board, blank_cell_idx = CreateBoard(num_rows, num_cols, num_cells)
        if not isGameOver(game_board, size):
            break
    # 游戏主循环
    is_running = True
    while is_running:
        # --事件捕获
        for event in pygame.event.get():
            # ----退出游戏
            if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                pygame.quit()
                sys.exit()
            # ----键盘操作
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT or event.key == ord('a'):
                    blank_cell_idx = moveL(game_board, blank_cell_idx, num_cols)
                elif event.key == pygame.K_RIGHT or event.key == ord('d'):
                    blank_cell_idx = moveR(game_board, blank_cell_idx, num_cols)
                elif event.key == pygame.K_UP or event.key == ord('w'):
                    blank_cell_idx = moveU(game_board, blank_cell_idx, num_rows, num_cols)
                elif event.key == pygame.K_DOWN or event.key == ord('s'):
                    blank_cell_idx = moveD(game_board, blank_cell_idx, num_cols)
            # ----鼠标操作
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                x, y = pygame.mouse.get_pos()
                x_pos = x // cell_width
                y_pos = y // cell_height
                idx = x_pos + y_pos * num_cols
                if idx == blank_cell_idx-1:
                    blank_cell_idx = moveR(game_board, blank_cell_idx, num_cols)
                elif idx == blank_cell_idx+1:
                    blank_cell_idx = moveL(game_board, blank_cell_idx, num_cols)
                elif idx == blank_cell_idx+num_cols:
                    blank_cell_idx = moveU(game_board, blank_cell_idx, num_rows, num_cols)
                elif idx == blank_cell_idx-num_cols:
                    blank_cell_idx = moveD(game_board, blank_cell_idx, num_cols)
        # --判断游戏是否结束
        if isGameOver(game_board, size):
            game_board[blank_cell_idx] = num_cells - 1
            is_running = False
        # --更新屏幕
        screen.fill(cfg.BACKGROUNDCOLOR)
        for i in range(num_cells):
            if game_board[i] == -1:
                continue
            x_pos = i // num_cols
            y_pos = i % num_cols
            rect = pygame.Rect(y_pos*cell_width, x_pos*cell_height, cell_width, cell_height)
            img_area = pygame.Rect((game_board[i]%num_cols)*cell_width, (game_board[i]//num_cols)*cell_height, cell_width, cell_height)
            screen.blit(game_img_used, rect, img_area)
        for i in range(num_cols+1):
            pygame.draw.line(screen, cfg.BLACK, (i*cell_width, 0), (i*cell_width, game_img_used_rect.height))
        for i in range(num_rows+1):
            pygame.draw.line(screen, cfg.BLACK, (0, i*cell_height), (game_img_used_rect.width, i*cell_height))
        pygame.display.update()
        clock.tick(cfg.FPS)
    # 游戏结束界面
    ShowEndInterface(screen, game_img_used_rect.width, game_img_used_rect.height)


'''run'''
if __name__ == '__main__':
    main()

4)效果展示

🐇随机效果展示最简单的模式👇

🐇随机效果展示中级难度模式👇

🐇随机效果展示最后一关模式👇

总结

🧧好啦今天内容and壁纸就到这里~

记得分享给你的闺蜜&对象,一起学习一起换壁纸哦!❤️

✨完整的素材源码等:可以滴滴我吖!或者点击文末hao自取免费拿的哈~

 🔨推荐往期文章——

项目4.4 【Pygame实战】这两款脑洞大开的文字剧情版游戏,99% 的人打了五星好评-《巨龙之洞》-《太空矿工》

项目0.6 【Python实战项目】做一个 刮刮乐 案例,一不小心....着实惊艳到我了。

项目0.3  【Pygamre实战】2023人气超高的模拟经营类游戏:梦想小镇代码版火爆全场,免费体验分享下载哦~

项目0.1  宝藏拼图神秘上线,三种玩法刷爆朋友圈—玩家直呼太上瘾了。

项目0.2 【Pygame小游戏】Python版有迷宫嘛?原来藏在个地方呀~

🎁文章汇总——

Python文章合集 | (入门到实战、游戏、Turtle、案例等)

(文章汇总还有更多你案例等你来学习啦~源码找我即可免费!) 

以上是关于兔年首文迎新春-Cesium橘子洲烟花礼赞的主要内容,如果未能解决你的问题,请参考以下文章

[Review]Tot Garden Spring Festival Celebration辞旧迎新,我们一起迎新春

币银亚洲强势上线,携双重奖赏迎新春!

西安北大青鸟-迎新春庆元旦+java知识竞赛!

好看的免费QQ空间代码

使用 JavaScript 创建一个兔年春节倒数计时器

使用 JavaScript 创建一个兔年春节倒数计时器