python 战棋游戏代码实现(1):生物行走和攻击选择
python 战棋游戏代码实现(1):生物行走和攻击选择
- 游戏介绍
- 代码介绍
- 地图类
- 确定人物行走范围
- 人物行走代码
- 生物状态机实现
- 完整代码
- 编译运行
游戏介绍
致敬永远的经典英雄无敌3, 本想在网上找个战棋游戏学习下,无奈没有发现python版本的,那就自己来写一个把。
游戏实现了类似英雄无敌3 中战斗场景的回合制玩法:
- 对战双方每个生物每一轮有一次行动机会,可以行走或攻击对方。
- 每个生物属性有:行走范围,速度,生命,伤害,防御,攻击 和 是否是远程兵种。
- 当把对方生物都消灭时,即胜利。
- 实现了简单的AI。
python 战棋游戏代码实现(2):六边形地图寻路和显示
生物行走选择截图如下:
图1
图1 中的步兵行走范围属性值是4,表示可以走4个方格,图中背景是深蓝色的方格就是该步兵可以走的方格,不可以直接到斜对角的方格。步兵头顶红色的是血条,当前轮到行动的生物背景方格颜色会变成浅蓝色。
游戏截图如下:
图2
图2中,目前轮到行动的生物是我方的左下角背景为浅蓝色的步兵,可以看到背景为深蓝色的方格为步兵可以行走的范围。背景为绿色的方格为目前选定要行走到得方格。鼠标指向敌方生物,如果敌方生物背景方格颜色变成黄色,表示可以攻击,可以看到允许攻击斜对角的敌人。图中还有石块,表示不能移动到得方格。
下面图3 是第二轮时我方开始行动时的截图。
代码介绍
地图类
source\component\map.py 中的 map类保存地图信息,width 和 height 为地图的宽度和长度,bg_map 设置方格的背景颜色, entity_map 保存哪个方格上有生物。active_entity表示当前要行动的生物。
class Map():def __init__(self, width, height, grid):self.width = widthself.height = heightself.bg_map = [[0 for x in range(self.width)] for y in range(self.height)]self.entity_map = [[None for x in range(self.width)] for y in range(self.height)]self.active_entity = None
updateMap 函数,当我方生物选择行动时,设置生物可行走范围内的方格背景为 c.BG_RANGE 。active_entity 的 inRange 函数判断一个方格是否在行走范围内。
def updateMap(self):for y in range(self.height):for x in range(self.width):self.bg_map[y][x] = c.BG_EMPTYif self.entity_map[y][x] is not None and self.entity_map[y][x].isDead():self.entity_map[y][x] = Noneif self.active_entity is None or self.active_entity.state != c.IDLE:returnmap_x, map_y = self.active_entity.map_x, self.active_entity.map_yself.bg_map[map_y][map_x] = c.BG_ACTIVEfor y in range(self.height):for x in range(self.width):if not self.isMovable(x,y):continueif self.active_entity.inRange(self, x, y):self.bg_map[y][x] = c.BG_RANGEmouse_x, mouse_y = pg.mouse.get_pos()self.checkMouseMove(mouse_x, mouse_y)
drawBackground 函数根据 bg_map 中每个方格的类型 绘制方格的背景颜色, 然后绘制方格之前的黑色分隔线。
def drawBackground(self, surface):pg.draw.rect(surface, c.LIGHTYELLOW, pg.Rect(0, 0, c.MAP_WIDTH, c.MAP_HEIGHT))for y in range(self.height):for x in range(self.width):if self.bg_map[y][x] == c.BG_EMPTY:color = c.LIGHTYELLOWelif self.bg_map[y][x] == c.BG_ACTIVE:color = c.SKY_BLUEelif self.bg_map[y][x] == c.BG_RANGE:color = c.NAVYBLUEelif self.bg_map[y][x] == c.BG_SELECT:color = c.GREENelif self.bg_map[y][x] == c.BG_ATTACK:color = c.GOLDpg.draw.rect(surface, color, (x * c.REC_SIZE, y * c.REC_SIZE, c.REC_SIZE, c.REC_SIZE))surface.blit(self.map_image, self.rect)for y in range(self.height):# draw a horizontal linestart_pos = (0, 0 + c.REC_SIZE * y)end_pos = (c.MAP_WIDTH, c.REC_SIZE * y)pg.draw.line(surface, c.BLACK, start_pos, end_pos, 1)for x in range(self.width):# draw a horizontal linestart_pos = (c.REC_SIZE * x, 0) end_pos = (c.REC_SIZE * x, c.MAP_HEIGHT)pg.draw.line(surface, c.BLACK, start_pos, end_pos, 1)
确定人物行走范围
source\component\entity.py 中的entity类保存生物的状态和属性。group表示 生物属于敌我哪一方, map_x 和 map_y 表示初始时生物在地图上的位置。sheet是生物的图像,EntityAttr 类保存生物的所有属性。
class Entity():def __init__(self, group, sheet, map_x, map_y, data):self.group = groupself.group_id = group.group_idself.map_x = map_xself.map_y = map_yself.frames = []self.frame_index = 0self.loadFrames(sheet)self.image = self.frames[self.frame_index]self.rect = self.image.get_rect()self.rect.x = self.map_x * c.REC_SIZE + 5self.rect.y = self.map_y * c.REC_SIZE + 8self.attr = EntityAttr(data)self.health = self.attr.max_healthself.weapon = Noneself.enemy = Noneself.state = c.IDLEself.animate_timer = 0.0self.current_time = 0.0self.move_speed = c.MOVE_SPEED
从图2 可以看到如果在生物的行走范围中有其他生物或石块时,行走范围就不能直接判断出来。
Entity类中 inRange函数使用A寻路算法计算出到某一个方格的距离,判断是否在行走范围内。
A 算法的实现说明可以看我之前的一篇文章 A*算法实现
def inRange(self, map, map_x, map_y):location = AStarSearch.AStarSearch(map, (self.map_x, self.map_y), (map_x, map_y))if location is not None:_, _, distance = AStarSearch.getFirstStepAndDistance(location)if distance <= self.attr.range:return Truereturn False
人物行走代码
A*算法可以获取从起始位置到目标位置的一条最短路径,所以人物行走就是沿着这个路径从起始位置移动到目标位置。
walkToDestination 函数中 self.rect.x 和 self.rect.y 表示生物当前的坐标位置,self.next_x 和self.next_y 表示路径中下一个方格的坐标位置。
- 当前的坐标位置和下一个方格的坐标位置相同时,选取路径中下一个方格的坐标位置。
- 当前的坐标位置和下一个方格的坐标位置不同时,生物就继续行走。
def walkToDestination(self, map):if self.rect.x == self.next_x and self.rect.y == self.next_y:source = (self.rect.x//c.REC_SIZE, self.rect.y//c.REC_SIZE)dest = (self.dest_x//c.REC_SIZE, self.dest_y//c.REC_SIZE)location = AStarSearch.AStarSearch(map, source, dest)if location is not None:map_x, map_y, _ = AStarSearch.getFirstStepAndDistance(location)self.next_x = map_x * c.REC_SIZE + 5self.next_y = map_y * c.REC_SIZE + 8else:self.state = c.IDLEprint('Error no path to walk to dest(%d,%d)' % (self.next_x, self.next_y))if self.rect.x != self.next_x:self.rect.x += self.move_speed if self.rect.x < self.next_x else -self.move_speedelif self.rect.y != self.next_y:self.rect.y += self.move_speed if self.rect.y < self.next_y else -self.move_speed
生物状态机实现
生物目前有3个状态:
- c.IDLE:没有轮到该生物行动时,不做任何操作
- c.WALK:轮到该生物行动时,从目前位置移动到指定的目标位置(self.dest_x, self.dest_y)
- c.ATTACK: 如果有可攻击的敌人时,按照生物是远程还是近程兵种,进行攻击。
def update(self, game_info, map):self.current_time = game_info[c.CURRENT_TIME]if self.state == c.WALK:if (self.current_time - self.animate_timer) > 250:if self.frame_index == 0:self.frame_index = 1else:self.frame_index = 0self.animate_timer = self.current_timeif self.rect.x != self.dest_x or self.rect.y != self.dest_y:self.walkToDestination(map)else:map.setEntity(self.map_x, self.map_y, None)self.map_x = self.dest_x // c.REC_SIZEself.map_y = self.dest_y // c.REC_SIZEmap.setEntity(self.map_x, self.map_y, self)if self.enemy is None:self.state = c.IDLEelse:self.state = c.ATTACKelif self.state == c.ATTACK:if self.attr.remote:if self.weapon is None:self.shoot(self.enemy)else:self.weapon.update()if self.weapon.done:self.weapon = Noneself.enemy = Noneself.state = c.IDLEelse:self.putHurt(self.enemy)self.enemy = Noneself.state = c.IDLEif self.state == c.IDLE:self.frame_index = 0
完整代码
游戏实现代码的github链接 战棋游戏
这边是csdn的下载链接 战棋游戏
编译运行
1.编译环境
python3.7 + pygame1.9
2.运行
直接运行根目录下的 main.py
$ python main.py
python 战棋游戏代码实现(1):生物行走和攻击选择相关推荐
- python 战棋游戏代码实现(2):六边形地图寻路和显示
python 战棋游戏代码实现(2):六边形地图寻路和显示 六边形地图介绍 代码介绍 地图六边形显示 A*算法的六边形寻路修改 判断某个点在哪个六边形中 完整代码 编译运行 六边形地图介绍 之前的文章 ...
- python 战棋游戏代码实现
游戏介绍 致敬永远的经典英雄无敌3, 本想在网上找个战棋游戏学习下,无奈没有发现python版本的,那就自己来写一个把. 游戏实现了类似英雄无敌3 中战斗场景的回合制玩法: 对战双方每个生物每一轮有一 ...
- HTML5 canvas 实现回合制战棋游戏(1):加载和绘制图形
HTML5 canvas 实现回合制战棋游戏(1):加载和绘制图形 游戏介绍 完整代码 代码目录 游戏运行 HTML5 canvas 绘制图形 canvas 介绍 绘制函数 加载图片 生物行走动画绘制 ...
- 一步一步教你用 Python 开发战棋游戏,仿英雄无敌
英雄无敌,你从没有玩过的"船"新版本-- 制作人:你自己-- 相信很多人都是从游戏开始接触电脑和编程的.很多人打算学习编程的时候,也都是冲着开发游戏去的,尤其是学习 Python ...
- pygame战棋游戏制作之战棋回合切换(五)
简介 前面我们已经完成了战棋地图的绘制,棋子的设置,光标的设置,接下来我们将要开始实现rpg游戏的灵魂--回合切换. 正文 回合切换主要是通过棋子列表判断,当列表为空时,触发回合切换的函数.因此我们创 ...
- UE战棋游戏的制作流程(使用GAS来制作技能系统)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 角色基础功能 GAS插件的使用 配置GameplaySystemAbility 角色的基本属性 创建结构体用于储存GE ...
- 酱油带你用cocos2dx3.0完成一款战棋游戏 (曹操传)(一)地图制作篇 1
这是酱油第一次写博客,所以如果有什么写的不好,大家多多海涵啊.那么废话就不多说了,直接进入正题吧. 制作一款战棋游戏,在酱油看来最大的难度便是 ai的设计以及 实现剧本对游戏整体的控制,当然啦,这都是 ...
- 【NOIP模拟赛】战棋游戏
战棋游戏 Description Rainbow擅长战棋类游戏.著名的战棋游戏有很多,例如<曹操传>.<瓦岗山异闻录>等.在本题中,我们考虑战棋游戏的一个简单版本,基于一下规则 ...
- NOIP2018 模拟测试 day1 战棋游戏
题目: 战棋游戏 Rainbow 擅长玩战棋类游戏.著名的战棋游戏有很多,例如<曹操传>.<瓦岗 山异闻录>等.在本题中,我们考虑战棋游戏的一个简单版本,基于以下规则: ⚫ 地 ...
- Java版桌面战棋游戏TLOH The Legend of Heroes 开发预告
按照本年度计划,年内笔者将继续开发Loonframework,前年及去年写的一些陈旧代码将被替换,有部分架构将重写.但实际上讲,剔除的代码中很多上并非不可用,而仅仅是不够规范,需要重构以满足组件化需要 ...
最新文章
- NPOI 导出Excel
- vue2.0通过Axios导出excel文件(解决乱码问题)
- T-SQL and XML
- mysql binlog rotate_binlog rotate引发的MySQL阻塞事件
- jeecg扩展字段,非实体属性
- ubuntu下安装优化调节软件——ubuntu tweakailurus
- python读取与写入配置文件
- 什么是Web Server
- 二分图 洛谷P2055 [ZJOI2009]假期的宿舍
- 米勒-拉宾素性检验(MillerRabbin)算法详解
- Android动态生成答题卡,手机扫描答题卡改卷的最佳选择——ZipGrade
- (转)高盛报告:人工智能、机器学习和数据将推动未来生产力的发展
- 保存360锁屏壁纸批量修改文件后缀名
- RANSAC的实现与应用
- 如何使用HTML5+CSS3绘制一个QQ 企鹅Logo
- 小米面试offer加油
- ORACLE 日期加减函数
- 微生物16S测序数据的正确打开方式
- Linux安装RPM包、查看本机ip和端口、手动配置ip、中标麒麟无法显示ip地址的详细解决方法
- Element Plus 虚拟化表格组件的使用(排序、筛选、自定义单元格渲染) - 个人使用总结
热门文章
- 中国银行app,H5页面调取支付,并返回状态码。
- JAE触摸屏维修JAE人机界面维修UT3-TS5-B
- antd 表单通过form.getFieldsValue获取不全tabs组件下表单数据的问题
- 给自己定一系列小目标
- BZOJ 2429: [HAOI2006]聪明的猴子
- zoj3551 Bloodsucker//概率dp
- 思维导图 基础篇(03)思维方法-发散/聚合思维
- 最简单linux桌面环境,推荐:轻型简易的Linux桌面环境
- python添加背景图片_Python实例 tkinter canvas (设置背景图片及文字)
- 论我是如何被自己搭建的聊天机器人气死的(自己的搞笑经历)