python练手--自制俄罗斯方块(文末附源码)

小白python学习中,刚把面向对象弄了个大概,打算找个项目练练手,于是决定做一个俄罗斯方块吧!然后到现在一个月就过去了。。。。。

期间接触了一下pygame,参考了目光博客的Pygame教程,当时感觉看懂了,等到用的时候,哈哈哈,感觉把pygame用成了画图程序。。。。。

其实,到现在我的俄罗斯方块也只是完成了一个DEMO,还有很多东西没有完善,而且也没考虑过性能,不过要出差一段时间不能学习了,所以决定先把DEMO发出来,等回头再来填坑。。。。。

整个程序如果不看注释,只看代码,应该大概是400行吧,运行时图如下,


主要说一下显示区,方块系统,和碰撞检测的思路吧,其他的都比较简单了。

显示区,通过维护四个列表,分别记录正在下落方块和已经落地方块的坐标和颜色,之后在把方块画出来。这里的坐标不是方块在窗口显示位置的坐标,而是列表内的‘相对坐标’,其实就是索引值。

什么是列表内的‘相对坐标’呢,这个得先说一下这个列表是什么鬼。


因为我的显示区,是一个以20像素的方块为单位,一共宽10个方块,高22个方块的区域,所以我的想法是,建立一个12*26的列表来与之对应(为什么是12*26呢,一开始我确实是做了一个10*22的列表,不过后来为了加入边界,把列表加到了12*23,再后来为了让方块从屏幕外一格一格进入显示区,就变成了12*26,这些后面再说。。。),在这个12*26的列表里面,0表示没有方块,1表示左右边界和下边界,然后当方块进入显示区以后,0变成1,表示此处有方块,而刚才所说的相对坐标,其实就是这个列表的索引值了。

这样我们有了相对坐标系,不过还不能用它来画方块,因为pygame画方块需要窗口坐标,所以我还要把相对坐标转换成屏幕坐标,比较简单,就是坐标系换算,一道数学题而已。

然后方块系统,我的方块系统只包括了上下左右四个操作,分别对应了旋转,向下移动一格,向左移动一格,向右移动一格,我把他们做成一个类的四个方法,其中左右下三个操作很简单,坐标加1减1就可以了,就是上操作,旋转,比较麻烦,没想到好办法,我只能将7个方块的所有状态一一编号,然后把旋转时坐标的相对变化全都写出来,累。。。。。中间还加上了贴墙位移,是为了防止旋转以后方块进到墙里面去,或者因为与墙面发生碰撞检测而导致不能旋转的情况。

算旋转时坐标变化的草图如下(要注意转一圈以后能转回初始位置,不然一直转的话,方块会产生位移)


再然后是碰撞检测,原理就是先记录动作前的坐标,然后执行动作,判断动作后的坐标,与墙面,与已经落地方块的坐标,是否重合。因为碰撞检测在每一次动作的时候都要执行一次,所以在实现的时候,我把它做成了一个装饰器,装饰在方块类上。(为了做这个装饰器,现学的如何对类进行装饰。。。。。)

其他的还有一个自己做的用来完成坐标运算的类,非常简陋,因为只是为了一次使用做的,所以只有一个加法运算,而且没有优化。这个类是参考了目光博客pygame教程里面向量运算的类做的。

剩下的就是逻辑了,本来以为写逻辑很简单的,没想到写逻辑写到一度怀疑自己没有逻辑。。。。尤其是,一直想做的按住左键就能一直向左移动的功能,感觉应该可以靠逻辑实现,不过到目前还没想出来。

总结写俄罗斯方块这一段时间的学习,对类有了新的认识,之前觉得类主要就是为了继承而存在的,不过这次虽然也写了类,却没用到继承,反而发现类的属性简直太好用了!!!

对于俄罗斯方块这个程序来说,感觉最难的是一开始,构想如何把方块画出来,这里还要考虑方块旋转,还要考虑以后消除行的时候能不能操作,还要考虑碰撞检测。最开始没有决定用列表和坐标解决这个问题的时候,还考虑过用精灵表示一个方块,不过方块是不规则的,不知道如何来做碰撞检测,上网去搜,在网上看见小甲鱼有一个飞机大战里面讲到对透明部分进行处理,然后完成不规则的碰撞检测,不过没有搞懂,去研究官方文档也没搞懂,还有什么掩码什么的,也是搞得我晕头转向,所以不得不暂时放弃了使用精灵的打算,看来想入门游戏要学的还有太多,手动哭一个吧。。。。

最后附上代码,和代码下载地址,欢迎讨论,欢迎指导,一起成长,手动笑。

下载地址,http://download.csdn.net/detail/highmiao_19/9868601

代码如下:

#俄罗斯方块
# -*- coding: utf-8 -*-
import pygame, random, time
from pygame.locals import *

pygame.init()
#pygame.key.set_repeat(1, 100)    #重复输入模式
#窗口
screen = pygame.display.set_mode((660,520), 0, 32)

#静态界面(背景、色块等)
interface = pygame.image.load(r'C:\Users\Administrator\Desktop\interface.jpg').convert()
gameover = pygame.image.load(r'C:\Users\Administrator\Desktop\GAME_OVER.jpg').convert()

#方块名称、颜色、初始位置
squares_dict = {0:'z_left', 1:'z_right', 2:'long', 3:'cross', 4:'rect', 5:'l_left', 6:'l_right'}
'''color_dict用于实例化的时候生成颜色标记'''
color_dict = {'z_left':1, 'z_right':2, 'long':3, 'cross':4, 'rect':5, 'l_left':6, 'l_right':7}
'''color_sheet用于表示颜色标记对应的颜色RGB'''
color_sheet = {1:(231,63,136), 2:(192,219,64), 3:(168,201,206), 4:(143,111,161), 5:(254,252,66), 6:(59,140,170), 7:(249,159,15)}
init_pos_dict = {'z_left':[(4,1), (5,1), (5,2), (6,2)],
                 'z_right':[(7,1), (6,1), (6,2), (5,2)],
                 'long':[(4,2), (5,2), (6,2), (7,2)],
                 'cross':[(5,1), (6,1), (7,1), (6,2)],
                 'rect':[(5,1), (6,1), (5,2), (6,2)],
                 'l_left':[(4,1), (5,1), (6,1), (6,2)],
                 'l_right':[(7,
  • 19
    点赞
  • 152
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值