【pygame实现星露谷物语风格游戏】6.工具的切换,种子的切换

一.前言

上一次,我们完成了实用工具的动画,但是并不能切换工具,这次我们要实现的功能是:按键盘左边shif键,切换工具。此外,还要完成种子的切换和使用,按下键盘右边的键,切换种子,按下右边ctrl键,使用种子。但是在这节并不会实现使用种子的动画,把他们放在以及只是因为他们切换的代码十分相似。

二.思路

分别创建列表存放工具和种子的名字,再分别创建索引,通过 改变索引的方式来获得我们正在使用的工具或者种子的名字:

同时,也写一个使用种子的函数,不过把它pass掉,留着以后再完善

接下来是写在input函数里面的键盘检测的代码:

#按下左边的shift键更换工具

if keys[pygame.K_LSHIFT] and not self.timers['tool switch'].active:

    self.timers['tool switch'].activate()

    self.tool_index += 1

    self.tool_index = self.tool_index if self.tool_index < len(self.tools) else 0

    self.selected_tool = self.tools[self.tool_index]


#按下左边的ctrl键,使用种子

if keys[pygame.K_RCTRL]:

    self.timers['seed use'].activate()

    self.direction = pygame.math.Vector2()

    self.frame_index = 0


#按下右边的shift键,切换种子

if keys[pygame.K_RSHIFT] and not self.timers['seed switch'].active:

    self.timers['seed switch'].activate()

    self.seed_index += 1

    self.seed_index = self.seed_index if self.seed_index < len(self.seeds) else 0

    self.selected_seed = self.seeds[self.seed_index]

 

当我们按下一次键盘上的按键的时候,实际上每一次循环都会检测到键盘被按下,直到我们松开按键。所以我们自认为按下了一次左边的shift键来切换工具,实际上每一帧他都会执行一次if语句里面的代码,除非你能在一帧以内松开键盘。因此我们还需要创建切换工具和切换种子的计时器,当检测到按下一次切换的按键后,200ms内不会再进行检测了,这样就可以避免上述的问题。

相应的,我们还顺带创建了使用种子的计时器,不过目前我们还用不到这个计时器。

三.完整代码

player.py

import pygame

from settings import *

from support import *

from timer import Timer


class Player(pygame.sprite.Sprite):

    def __init__(self,pos,group):

        #这个参数可以传一个精灵组,这样就会自动把该精灵加入到该精灵组中

        #也可以为空,这样需要在外面手动调用精灵组的add函数来将这个精灵加入到精灵组中

        super().__init__(group)


        self.import_assets()

        self.status = 'down_idle'

        self.frame_index = 0


        #这里的变量名一定要叫image,因为这是它父类Sprite规定的

        self.image = self.animations[self.status][self.frame_index]



        #这个get_rect()也是父类中设置的方法

        #返回值是有很多,大概有x,y,centerx,centery,center,width,height这几类

        #大概就是image的x坐标,y坐标,中心的x坐标,中心的y坐标,中心点的坐标,宽度,高度等

        #参数可以不填,那么位置就默认是(0,0),也可以填一个列表,比如(100,100),那么初始的位置就是(100,100)

        #也可以是center = 一个坐标,这表示设置该图像的中心在这个坐标上

        #同样的这里的变量名也一定要叫rect,这是父类规定的

        self.rect = self.image.get_rect(center = pos)


        #创建一个二维的向量,参数不填默认是(0,0)

        self.direction = pygame.math.Vector2()#速度的方向

        self.pos = pygame.math.Vector2(self.rect.center)#位置

        self.speed = 200#速度


        self.timers = {

            'tool use':Timer(350,self.use_tool),

            'tool switch': Timer(200),

            'seed use': Timer(350, self.use_seed),

            'seed switch': Timer(200),

        }


        self.tools = ['hoe', 'axe', 'water']

        self.tool_index = 0

        self.selected_tool = self.tools[self.tool_index]


        self.seeds = ['corn', 'tomato']

        self.seed_index = 0

        self.selected_seed = self.seeds[self.seed_index]


    def use_tool(self):

        pass


    def use_seed(self):

        pass

    def import_assets(self):

        self.animations = {'up': [], 'down': [], 'left': [], 'right': [],

                           'right_idle': [], 'left_idle': [], 'up_idle': [], 'down_idle': [],

                           'right_hoe': [], 'left_hoe': [], 'up_hoe': [], 'down_hoe': [],

                           'right_axe': [], 'left_axe': [], 'up_axe': [], 'down_axe': [],

                           'right_water': [], 'left_water': [], 'up_water': [], 'down_water': []}


        for animation in self.animations.keys():

            full_path = '../graphics/character/' + animation

            self.animations[animation] = import_folder(full_path)


    def animate(self, dt):


        # 4 是比较合适的数字

        # 数字 决定做动作的快慢

        # 做一个动作需要 1/4秒

        # fream_index += dt 的话,要经过1s,才能变成下一个整数,做下一个动作

        # fream_index += 4*dt,那么增加的速度就快了四倍,经过1/4秒就能做下一个动作了

        self.frame_index += 4 * dt

        # print(self.frame_index)

        if self.frame_index >= len(self.animations[self.status]):

            self.frame_index = 0


        self.image = self.animations[self.status][int(self.frame_index)]


    def input(self):

        keys = pygame.key.get_pressed()

        #已经在使用工具的时候,停止对按键的检测

        if not self.timers['tool use'].active:

            if keys[pygame.K_UP]:

                self.direction.y = -1

                self.status = 'up'

            elif keys[pygame.K_DOWN]:

                self.direction.y = 1

                self.status = 'down'

            else:

                self.direction.y = 0#不要忘记加上这一句,不然按下键盘后再松开也不会停


            if keys[pygame.K_RIGHT]:

                self.direction.x = 1

                self.status = 'right'

            elif keys[pygame.K_LEFT]:

                self.direction.x = -1

                self.status = 'left'

            else:

                self.direction.x = 0


            if keys[pygame.K_SPACE]:

                #启动计时器

                self.timers['tool use'].activate()

                #实用工具的时候是不能移动的

                self.direction = pygame.math.Vector2()

                #要从第一张图片开始绘制

                self.frame_index = 0


            #按下左边的shift键更换工具

            if keys[pygame.K_LSHIFT] and not self.timers['tool switch'].active:

                self.timers['tool switch'].activate()

                self.tool_index += 1

                self.tool_index = self.tool_index if self.tool_index < len(self.tools) else 0

                self.selected_tool = self.tools[self.tool_index]


            #按下左边的ctrl键,使用种子

            if keys[pygame.K_RCTRL]:

                self.timers['seed use'].activate()

                self.direction = pygame.math.Vector2()

                self.frame_index = 0


            #按下右边的shift键,切换种子

            if keys[pygame.K_RSHIFT] and not self.timers['seed switch'].active:

                self.timers['seed switch'].activate()

                self.seed_index += 1

                self.seed_index = self.seed_index if self.seed_index < len(self.seeds) else 0

                self.selected_seed = self.seeds[self.seed_index]


    def get_status(self):


        # idle

        if self.direction.magnitude() == 0:

            # self.status += '_idle'

            # 上面这种方法不可取因为每一帧都会在字符串后面加上一个_idel

            # 所以status会变成 xxx_idle_idle_idle

            # 实际上当出现两个_idle的时候就已经报错了

            # 下面这种方法

            # split('_')是把一个字符串 以 '_' 为分节符分开

            # 他返回的是一个列表

            # 比如 a_b_c_d

            # 返回的就是[a,b,c,d]

            # 所以下面的【0】获取的就是_之前的内容

            self.status = self.status.split('_')[0] + '_idle'


        if self.timers['tool use'].active:

            self.status = self.status.split('_')[0] + '_' + self.selected_tool


    def update_timers(self):

        for timer in self.timers.values():

            timer.update()


    def move(self,dt):

        #向量归一化,比如一个n维向量为(x1,x2,x3...,xn)

        #那么向量归一化的操作就是等比例缩放x1到xn的大小让 根号下(x1的平方+x2的平方+...+xn的平方) 等于1

        #归一化的目的是如果同时按右键和上,那么direction就会变成(1,1),他的速度向量就是一个大小为根2,方向右上的向量了

        #magnitude()返回的是一个float类型的数据,他的大小为根号下(x1的平方+x2的平方+...+xn的平方)

        if self.direction.magnitude() > 0:#这表示如果有按键按下,如果向量里面全是0,会使归一化中的数学计算出现错误

            self.direction = self.direction.normalize()


        #位移 = 方向 * 速度 * 变化的时间()

        self.pos.x += self.direction.x * self.speed * dt

        self.rect.centerx = self.pos.x


        self.pos.y += self.direction.y * self.speed * dt

        self.rect.centery = self.pos.y


    def update(self,dt):

        self.input()

        self.get_status()

        self.update_timers()


        self.move(dt)

        self.animate(dt)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

owooooow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值