python人物代码_Python 超级玛丽代码实现:人物行走和碰撞检测

游戏代码

游戏实现代码的github链接 超级玛丽

这边是csdn的下载链接 超级玛丽

代码介绍

人物行走代码

有一个单独的人物类,在source\components\player.py 中,其中有个handle_state 函数,根据人物当前的状态执行不同的函数。

为了简洁下面所有函数中将不相关的代码都省略掉了。

代码已打包,学习python可加交流群:887934385 分享视频教程

1 学习python可加交流群:887934385分享视频教程2 defhandle_state(self, keys, fire_group):3 if self.state ==c.STAND:4 self.standing(keys, fire_group)5 elif self.state ==c.WALK:6 self.walking(keys, fire_group)7 elif self.state ==c.JUMP:8 self.jumping(keys, fire_group)9 elif self.state ==c.FALL:10 self.falling(keys, fire_group)

人物的状态就是上面说的4个状态:

站立不动:c.STAND

向左或向右走:c.WALK

向上跳:c.JUMP

向下降落:c.FALL

人物类关于行走速度的成员变量先了解下:

水平方向相关的

x_accel:水平方向的加速度,值大于0,不区别方向。

max_x_vel:水平方向的最大速度,值大于0,不区别方向。

x_vel:水平方向的速度,值大于0表示向右走,值小于0表示向左走。

初始值:max_run_vel和max_walk_vel 表示最大速度,run_accel和walk_accel表示加速度。

facing_right:值为True表示当前是向右走,值为False表示当前是向左走,这个是用来设置人物的图像。

竖直方向相关的

gravity:重力加速度,值大于0,表示方向向下。

jump_vel:起跳时竖直方向的初始速度,值小于0,表示方向向上。

y_vel:竖直方向的速度。

看下最复杂的 walking 函数,keys数组是当前按下的键盘输入,tools.keybinding中值的含义如下:

1 keybinding ={2 'action':pg.K_s,3 'jump':pg.K_a,4 'left':pg.K_LEFT,5 'right':pg.K_RIGHT,6 'down':pg.K_DOWN7 }

先根据当前是否有按下 keybinding[‘action’] 键来设置不同的最大水平方向速度和水平方向加速度。

如果有按下 keybinding[‘jump’] 键,则设置人物状态为c.JUMP,初始化竖直方向的速度

如果有按下keybinding[‘left’]键,表示要向左走,如果 x_vel 大于0,表示之前是向右走的,所以设置一个转身的加速度为SMALL_TURNAROUND,然后调用cal_vel 函数根据之前的速度和加速度,计算出当前的速度。

如果有按下keybinding[‘right’]键,表示要向右走,和上面类似

如果没有按下keybinding[‘left’]键和keybinding[‘right’]键,就像有摩擦力的存在,则水平方向的速度会慢慢变成0,如果 x_vel 值为0,则设置人物状态为c.STAND。

1 defwalking(self, keys, fire_group):2 if keys[tools.keybinding['action']]:3 self.max_x_vel =self.max_run_vel4 self.x_accel =self.run_accel5 else:6 self.max_x_vel =self.max_walk_vel7 self.x_accel =self.walk_accel8

9 if keys[tools.keybinding['jump']]:10 ifself.allow_jump:11 self.state =c.JUMP12 if abs(self.x_vel) > 4:13 self.y_vel = self.jump_vel - .5

14 else:15 self.y_vel =self.jump_vel16

17 if keys[tools.keybinding['left']]:18 self.facing_right =False19 if self.x_vel >0:20 self.frame_index = 5

21 self.x_accel =c.SMALL_TURNAROUND22

23 self.x_vel =self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel, True)24 elif keys[tools.keybinding['right']]:25 self.facing_right =True26 if self.x_vel <0:27 self.frame_index = 5

28 self.x_accel =c.SMALL_TURNAROUND29

30 self.x_vel =self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel)31 else:32 ifself.facing_right:33 if self.x_vel >0:34 self.x_vel -=self.x_accel35 else:36 self.x_vel =037 self.state =c.STAND38 else:39 if self.x_vel <0:40 self.x_vel +=self.x_accel41 else:42 self.x_vel =043 self.state =c.STAND44

45 def cal_vel(self, vel, max_vel, accel, isNegative=False):46 """max_vel and accel must > 0"""

47 ifisNegative:48 new_vel = vel * -1

49 else:50 new_vel =vel51 if (new_vel + accel) <52 new_vel else:54 ifisnegative:56 return>

57 else:58 return new_vel

再看下jumping 函数,

开始gravity 设为 c.JUMP_GRAVITY,可以看到JUMP_GRAVITY 比GRAVITY值小很多,如果玩家长按jump键时,可以让人物跳的更高。

如果竖直方向速度y_vel 大于0,表示方向向下,则设置人物状态为c.FALL

如果按下 keybinding[‘left’]键或 keybinding[‘right’]键,则计算水平方向的速度。

如果没有按 keybinding[‘jump’]键,则设置人物状态为c.FALL

1 JUMP_GRAVITY = .31

2 GRAVITY = 1.01

3

4 defjumping(self, keys, fire_group):5 """y_vel value: positive is down, negative is up"""

6 self.allow_jump =False7 self.frame_index = 4

8 self.gravity =c.JUMP_GRAVITY9 self.y_vel +=self.gravity10

11 if self.y_vel >= 0 and self.y_vel <12 self.gravity="c.GRAVITY13" self.state="c.FALL14</p">

15 if keys[tools.keybinding['right']]:16 self.x_vel =self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel)17 elif keys[tools.keybinding['left']]:18 self.x_vel =self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel, True)19

20 if not keys[tools.keybinding['jump']]:21 self.gravity =c.GRAVITY22 self.state = c.FALL

standing函数和 falling 函数比较简单,就省略了。

碰撞检测代码

人物的碰撞检测代码在 source\states\level.py 中的入口是

update_player_position函数 ,可以看到这边分成水平方向和竖直方向:

根据人物的水平方向速度x_vel 更新人物的X轴位置,同时人物的X轴位置不能超出游戏地图的X轴范围,然后调用check_player_x_collisions函数进行水平方向的碰撞检测。

根据人物的水平方向速度x_vel 更新人物的X轴位置,同时人物的X轴位置不能超出游戏地图的X轴范围,然后调用check_player_x_collisions函数进行水平方向的碰撞检测。

根据人物的竖直方向速度y_vel 更新人物的Y轴位置,然后调用check_player_y_collisions函数进行竖直方向的碰撞检测

1 defupdate_player_position(self):2 self.player.rect.x +=round(self.player.x_vel)3 if self.player.rect.x <4 self.player.rect.x="self.start_x5" elif self.player.rect.right>self.end_x:6 self.player.rect.right =self.end_x7 self.check_player_x_collisions()84>

9 if notself.player.dead:10 self.player.rect.y +=round(self.player.y_vel)11 self.check_player_y_collisions()

具体实现时将同一类物体放在一个pygame.sprite.Group类中

1 pygame.sprite.Group2 A container class to hold andmanage multiple Sprite objects.3 Group(*sprites) -> Group

这样每次调用pg.sprite.spritecollideany 函数就能判断人物和这一类物体是否有碰撞。

1 pygame.sprite.spritecollideany()2 Simple test if a sprite intersects anything ina group.3 spritecollideany(sprite, group, collided = None) ->Sprite Collision with the returned sprite.4 spritecollideany(sprite, group, collided = None) -> None No collision

不同物体的group如下,另外敌人,金币和蘑菇等物体的碰撞检测先忽略。

ground_step_pipe_group:地面,阶梯和水管的group。

brick_group:砖块的group, 如果是金币砖块,从下面碰撞会获取金币。

box_group:箱子的group,从下面碰撞箱子可以出现金币,蘑菇,花等的奖励。

因为不同种类group撞击时,后续产生的结果会有区别,所有需要对每一类group分别进行碰撞检测。

X轴方向上面3类group如果检测到有碰撞时,会调用adjust_player_for_x_collisions 函数,来调整人物的X轴位置。

1 defcheck_player_x_collisions(self):2 ground_step_pipe =pg.sprite.spritecollideany(self.player, self.ground_step_pipe_group)3 brick =pg.sprite.spritecollideany(self.player, self.brick_group)4 box =pg.sprite.spritecollideany(self.player, self.box_group)5 ...6 ifbox:7 self.adjust_player_for_x_collisions(box)8 elifbrick:9 self.adjust_player_for_x_collisions(brick)10 elifground_step_pipe:11 if (ground_step_pipe.name == c.MAP_PIPE and

12 ground_step_pipe.type ==c.PIPE_TYPE_HORIZONTAL):13 return

14 self.adjust_player_for_x_collisions(ground_step_pipe)15 elifpowerup:16 ...17 elifenemy:18 ...19 elifcoin:20 ...

adjust_player_for_x_collisions函数先根据人物和碰撞物体的X轴相对位置,判断人物在碰撞物体的左边还是右边,来调整人物的X轴位置,然后设置人物水平方向的速度为0。

1 defadjust_player_for_x_collisions(self, collider):2 if collider.name ==c.MAP_SLIDER:3 return

4

5 if self.player.rect.x <6 self.player.rect.right="collider.rect.left7" else:8 self.player.rect.left="collider.rect.right9" self.player.x_vel="0</p">

学习python可加交流群:887934385 分享视频教程

check_player_y_collisions 函数也是对不同group分别进行碰撞检测,Y轴方向这3类group如果检测到有碰撞时,会调用adjust_player_for_y_collisions 函数,来调整人物的Y轴位置。 最后调用check_is_falling函数判断人物是否要设成 向下降落 的状态。

1 defwalking(self, keys, fire_group):2 if keys[tools.keybinding['action']]:3 self.max_x_vel =self.max_run_vel4 self.x_accel =self.run_accel5 else:6 self.max_x_vel =self.max_walk_vel7 self.x_accel =self.walk_accel8

9 if keys[tools.keybinding['jump']]:10 ifself.allow_jump:11 self.state =c.JUMP12 if abs(self.x_vel) > 4:13 self.y_vel = self.jump_vel - .5

14 else:15 self.y_vel =self.jump_vel16

17 if keys[tools.keybinding['left']]:18 self.facing_right =False19 if self.x_vel >0:20 self.frame_index = 5

21 self.x_accel =c.SMALL_TURNAROUND22

23 self.x_vel =self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel, True)24 elif keys[tools.keybinding['right']]:25 self.facing_right =True26 if self.x_vel <0:27 self.frame_index = 5

28 self.x_accel =c.SMALL_TURNAROUND29

30 self.x_vel =self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel)31 else:32 ifself.facing_right:33 if self.x_vel >0:34 self.x_vel -=self.x_accel35 else:36 self.x_vel =037 self.state =c.STAND38 else:39 if self.x_vel <0:40 self.x_vel +=self.x_accel41 else:42 self.x_vel =043 self.state =c.STAND44

45 def cal_vel(self, vel, max_vel, accel, isNegative=False):46 """max_vel and accel must > 0"""

47 ifisNegative:48 new_vel = vel * -1

49 else:50 new_vel =vel51 if (new_vel + accel) <52 new_vel else:54 ifisnegative:56 return>

57 else:58 return new_vel

52>6>12>52>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值