编程语言:python(3.6.4)

主要应用的模块:pygame

(下面有源码,但是拒绝分享完整的源码,下面的代码整合起来就是完整的源码)

首先列出我的核心思路:

1,图像由“核心变量”完全控制,图像变化的本质是 变量的改变

2,自上而下式的思考,图像变化的问题将一步步转为 一系列具体的变量修改

3,“核心变量”在思考过程中并非不可变更,为了写函数方便,可以适当让步

正文开始:

核心变量到图像

首先看成品图预览图

从上图和游戏玩法可以得出以下两点:

1,方块位置十分有规律

2,两类方块(上面移动的,下方固定的 都比较有特点)

方块的大小都是固定的,只需要操心位置的问题,下面建坐标系



下一步,坐标的储存方式

欢迎加群:725479218,完整源码,以及pygame的学习方法,都有

记录方式有两种:

 1,横纵坐标做一个二元元组,再用一个列表装着一堆二元元组

      例如:[(20,1),(20,2),(20,3),(20,4)]代表第20行的1~4列的四个方块

  2,二维数组,一行是一个列表,用两个索引代表横纵坐标,值为1就代表有方块,0就是没有方块

例如:block[20][1] 值为1就表示20行第1列有方块,block[20][5] 为0表示20行第5列有没有方块

讲道理,两种记录方式没什么大区别,而且第一种似乎更好用

但后面会有这样的问题

怎么判断一行是否被填满,填满后怎么消除,消除后怎么使上方的方块下落。

两种记录方式对应的解法:

    1,假如判断第2行 只要依次判断(2, 0), (2, 1)···· (2, 8), (2, 9) 是否都存在于列表就可以,消除、下落就有点麻烦,以第2行为例 遍历列表 2行以下的不修改,2行的全部清除,2行以上的 行数-1

    2,被填满 等价于 全是1 等价于 没有0 ,一个not in 就可以啦,pop就可以清除一行,而且后面列表的索引会向前补(实现下落),然后在最后补充一个空列表就完事啦(防止被删光)

所以

充当背景的方块 就使用2号记录方式

下一步 对接pygame绘制函数

核心变量的声明

background = [[0 for i in range(10)]for j in range(21)]
active = []

绘制函数

# 第一版
def new_draw():
screen.fill(white) for i in range(1, 21):
for j in range(10):
bolck = background[i][j]
if bolck:
pygame.draw.rect(screen, blue, (j * 25 + 1, 500 - i * 25 + 1, 23, 23)) for i, j in active:
pygame.draw.rect(screen, blue, (j * 25+1, 500 - i * 25 + 1, 23, 23)) pygame.display.update()

补充:坐标转换

键盘到图像(本质:键盘到核心变量)

下面简略列出需要的函数

首先,方块移动的难点在“旋转”上

Q:为什么不先考虑左右移动

A:旋转的问题的有些复杂,需要变更“核心变量”

核心变量一但变更 其它相关函数都得改写

所以为了省心,优先考虑可能涉及“核心变量”的事情

解决思路:

  1,为每个形状建立一个“状态库”,手写出每个姿态,旋转时再读取

  2,旋转前后存在明确的数学关系

选那个没有悬念

追加一个变量,记录旋转中心坐标

旋转时依照方程转换坐标

公式很简单吧

如果旋转在原点,将会更简单

PS:注意坐标系,公式不能直接抄

所以,从记录“绝对坐标”变更为“中心坐标+相对坐标”

PS:绘制函数需要做相应的调整

旋转过程 ( x , y ) --> (-y , x)

重要的细节:移动是有限制的

方块在边界处,就得限制向外的移动,如果移动后与已有的方块重叠,也得限制移动

代码时间

左右移动

def move_LR(n):
"""n=-1代表向左,n=1代表向右"""
x, y = centre
y += n
for i, j in active:
i += x
j += y
if j < 0 or j > 9 or background[i][j]:
break
else:
centre.clear()
centre.extend([x, y])

PS:centre是列表

Q:clear + extend 是什么骚操作?不可以直接赋值吗?

A:函数内部可以读取 但不能修改全局变量

但是可以调用全局变量的方法

所以clear+extend修改centra

这样就不用将centra传入传出啦

(危险操作,谨慎使用)

旋转的

def rotate():
x, y = centre
l = [(-j, i) for i, j in active]
for i, j in l:
i += x
j += y
if j < 0 or j > 9 or background[i][j]:
break
else:
active.clear()
active.extend(l)

PS:因为旋转的机制很简陋,会有田字形方块的也能旋转的奇怪现象发生。

讲道理下落并不难,关键是下落结束后会有很多后事要处理

  1,检查是否落到底部,是:继续,否:跳出

  2,active的信息转到background,

  3,检查background是否有“行”被填满 是:继续,否:跳至5

  4,清掉满行,补上空行,计分

  5,生成新的active,检查其位置是否被占(被占<=>方块被堆至顶部<=>game over)

那就开始撸代码

def move_down():
x, y = centre
x -= 1
for i, j in active:
i += x
j += y
if background[i][j]:
break
else:
centre.clear()
centre.extend([x, y])
return
# 如果新位置未被占用 通过return结束
# 如果新位置被占用则继续向下执行
x, y = centre
for i, j in active:
background[x + i][y + j] = 1 l = []
for i in range(1, 20):
if 0 not in background[i]:
l.append(i)
# l装 行号,鉴于删去后,部分索引变化,对其降序排列,倒着删除
l.sort(reverse=True) for i in l:
background.pop(i)
background.append([0 for j in range(10)])
# 随删随补 score[0] += len(l)
pygame.display.set_caption("分数:%d" % (score[0])) active.clear()
active.extend(list(random.choice(all_block)))
# all_block保存7种形状的信息,手打出来的
centre.clear()
centre.extend([20, 4]) x, y = centre
for i, j in active:
i += x
j += y
if background[i][j]:
break
else:
return
alive.append(1)

控制结构

下一步组装

因为核心变量发生变化,new_draw重写

def new_draw():
screen.fill(white) for i in range(1, 21):
for j in range(10):
bolck = background[i][j]
if bolck:
pygame.draw.rect(screen, blue, (j * 25 + 1, 500 - i * 25 + 1, 23, 23)) x, y = centre
for i, j in active:
i += x
j += y
pygame.draw.rect(screen, blue, (j * 25 + 1, 500 - i * 25 + 1, 23, 23)) pygame.display.update()

核心变量定义

all_block = (((0, 0), (0, -1), (0, 1), (0, 2)),
((0, 0), (0, 1), (-1, 0), (-1, 1)),
((0, 0), (0, -1), (-1, 0), (-1, 1)),
((0, 0), (0, 1), (-1, -1), (-1, 0)),
((0, 0), (0, 1), (1, 0), (0, -1)),
((0, 0), (1, 0), (-1, 0), (1, -1)),
((0, 0), (1, 0), (-1, 0), (1, 1)))
background = [[0 for i in range(10)] for j in range(24)]
background[0] = [1 for i in range(10)]
active = list(random.choice(all_block))
centre = [20, 4]
score = [0]
    for i in range(1, 20):
if 0 not in background[i]:
l.append(i)

这个部分是从第1行才开始检查的(~ ̄▽ ̄)~

3,我懒,不想传参,所以 老套路

pygame固定结构,控制结构,控制变量,龙套变量

pygame.init()
screen = pygame.display.set_mode((250, 500))
pygame.display.set_caption("俄罗斯方块")
fclock = pygame.time.Clock() black = 0, 0, 0
white = 255, 255, 255
blue = 0, 0, 255 times = 0
alive = []
press = False
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
move_LR(-1)
elif event.key == pygame.K_RIGHT:
move_LR(1)
elif event.key == pygame.K_UP:
rotate()
elif event.key == pygame.K_DOWN:
press = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
press = False
if press:
times += 10 if times >= 50:
move_down()
times = 0
else:
times += 1 if alive:
pygame.display.set_caption("over分数:%d" % (score[0]))
time.sleep(3)
break
new_draw()
fclock.tick(100)

说明:

1,原来按一次“下”,方块只会移动一格。。。。

所以修正了一下,支持 长按,为此加了一个变量press

2,times用于计时

3,游戏结束的有点突兀,直接就brake啦

最后发现漏了一行没拷上来

源码分享,加群获取:725479218

群里面可以获取学习pygame的学习方法

欢迎加入

python游戏开发之俄罗斯方块(一):简版的更多相关文章

  1. .Net Core ORM选择之路,哪个才适合你 通用查询类封装之Mongodb篇 Snowflake(雪花算法)的JavaScript实现 【开发记录】如何在B/S项目中使用中国天气的实时天气功能 【开发记录】微信小游戏开发入门——俄罗斯方块

    .Net Core ORM选择之路,哪个才适合你   因为老板的一句话公司项目需要迁移到.Net Core ,但是以前同事用的ORM不支持.Net Core 开发过程也遇到了各种坑,插入条数多了也特别 ...

  2. 网页游戏开发秘笈 PDF扫描版

    精选10种常见的游戏类型,透过典型实例,深入剖析游戏引擎及工具的选用技巧,详细讲解每款游戏的制作过程,为快速掌握网页游戏开发提供系统而实用的指南. 网页游戏开发秘笈 目录: 译者序  前 言  导 言 ...

  3. 分享《Python 游戏编程快速上手(第3版)》高清中文版PDF+高清英文版PDF+源代码

    通过编写一个个小巧.有趣的游戏来学习Python,通过实例来解释编程的原理的方式.14个游戏程序和示例,介绍了Python基础知识.数据类型.函数.流程控制.程序调试.流程图设计.字符串操作.列表和字 ...

  4. 【1】【MOOC】Python游戏开发入门-北京理工大学【第二部分-游戏开发之框架】

    学习地址链接:http://www.icourse163.org/course/0809BIT021E-1001873001?utm_campaign=share&utm_medium=and ...

  5. Coco2d-x android win7 Python 游戏开发环境的搭建

    1:我用的电脑配置 win7 3 核 内存8G 桌面.一直想学习Coco2d 游戏开发,所以,一个星期后,需要找到,最终建立了一个良好的环境 2:我使用的版本号版本号,至于建筑android开发环境略 ...

  6. iOS cocos2d 2游戏开发实战(第3版)书评

    2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...

  7. Python游戏开发:pygame游戏开发常用数据结构

    一.数组与列表 数组可以理解为简化的列表.像我们之前使用的pygame.sprite.Group这样的精灵组,也是一个列表.列表的元素是可变的,它具有添加.删除.搜索.排序等多种方法. 1.一维列表 ...

  8. Python游戏开发——打砖块

    打砖块游戏向来大家也不会很陌生,今天来用python来开发一下这个小游戏 1.引用对应数据库 import pygame from pygame.locals import * import sys, ...

  9. Python游戏编程入门 中文pdf扫描版|网盘下载内附地址提取码|

    Python是一种解释型.面向对象.动态数据类型的程序设计语言,在游戏开发领域,Python也得到越来越广泛的应用,并由此受到重视. 本书教授用Python开发精彩游戏所需的[]为重要的该你那.本书不 ...

随机推荐

  1. jQuery中bind() live() delegate() on() 的区别

    实例 bind(type,[data],fn) 为每个匹配元素的特定事件绑定事件处理函数 $("a").bind("click",function(){aler ...

  2. java集合类学习

    以下基于jdk1.8 一. 集合类关系图 1. 接口关系图 2.集合中的类,(不包含线程安全的) 二.ArrayList 1.类定义 /** * 用“可伸缩数组”来实现List接口.实现了所有List ...

  3. sqlserver 拆分

    有表tb, 如下:id value----------- -----------1 aa,bb2 aaa,bbb,ccc欲按id,分拆value列, 分拆后结果如下:id value--------- ...

  4. log4.net 配置-控制台输出带颜色的日志

    一般对控制台输入的日志我们使用的 Appender 为 ConsoleAppender ,日志为白色文字. 当我们想到 DEBUG,INFO,WARN,ERROR  每种日志设置一种颜色时我们需要将  ...

  5. January 09th, 2018 Week 02nd Tuesday

    Use the smile to change the world. Don't let the world change your smile. 用你的笑容去改变这个世界,别让这个世界改变了你的笑容 ...

  6. Beta冲刺(3/5)(麻瓜制造者)

    今日已完成 邓弘立:完成了登录功能的重构,完成了部分商品管理功能 符天愉:利用ci开始写队友写好的管理员界面,由于后台独立开始使用一个仓库,所以晚上将alpha的版本更新到了git,并且添加了.git ...

  7. Python3.6安装及引入Requests库

    本博客可能没有那么规范,环境之类的配置.只是让你直接开始编程写python. 至于各种配置网络上有多种方法. 本文仅代表我的观点的一种方法. 电脑环境:win10 64位 第一步:下载python. ...

  8. GUI_键盘事件

    import java.awt.Button; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.TextField ...

  9. 多个Activity和Intent

    Intent是Android应用程序组件之一,在Android系统当中表示一种意图,Intent中包含了一组信息: 最重要的内容是action(动作)和data(数据) Component name ...

  10. swift面向协议编程

    https://www.technotification.com/2018/08/protocol-oriented-programming-swift.html https://www.toptal ...