pygame-按下event.key上的键

时间:2018-07-24 20:35:20

标签: python pygame

我在使用pyGame时遇到问题(在此处完成新手操作)。我练习event.key,并且想取消/切断连续按下的键。我试图用谷歌搜索并检查了该站点,但是没有结果。整个事情都发生在

## HOW TO UNPRESS K_UP IN CASE IT WAS PRESSED AND NOT RELEASED?
    if event.key == pygame.K_UP and isJumping == False:
        yChange -= 10
        isJumping = True

    elif event.key == pygame.K_UP and isJumping == True:
        print("X")

(第49-55行)

import pygame

pygame.init() # Initialize pyGame module

# Set screen dimensions
screenW = 800
screenH = 600

# Set color
AQUA = (155, 255, 255)

# Set FPS
FPS = 60
fpsClock = pygame.time.Clock()

# Set character
mainChar = pygame.image.load('p1_front.png')
mainCharX = screenH / 2 # char X position
mainCharY = screenW / 2 # char Y position
isJumping = False
xChange = 0
yChange = 0
MOVSPEED = 1
# Set backgrounds
mainBg = pygame.image.load('bg_castle.png')
mainBg = pygame.transform.scale(mainBg, (screenW, screenH))

# Set the window, param in a tuple is width / height
DISPLAYSURF = pygame.display.set_mode((screenW, screenH))
# Set window name (game title)
pygame.display.set_caption("Newbie training")

while True: # Main loop of the game
#set BG
DISPLAYSURF.blit(mainBg, (0,0))

# Events loop below
for event in pygame.event.get():
    if event.type == pygame.QUIT: # Quit window when [x] is pressed
        pygame.quit()
        exit()

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_RIGHT:
            xChange += MOVSPEED
        elif event.key == pygame.K_LEFT:
            xChange -= MOVSPEED

        ## HOW TO UNPRESS K_UP IN CASE IT WAS PRESSED AND NOT RELEASED?
        if event.key == pygame.K_UP and isJumping == False:
            yChange -= 10
            isJumping = True

        elif event.key == pygame.K_UP and isJumping == True:
            print("X")



    if event.type == pygame.KEYUP:
        if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
            xChange = 0
        if event.key == pygame.K_UP:
            yChange = 0
    #print(event)

mainCharX += xChange
mainCharY += yChange
DISPLAYSURF.blit(mainChar, (mainCharX, mainCharY)) # Load character
pygame.display.update() #update window
fpsClock.tick(FPS) # FPS goes always after update

如果一次按下向上箭头,这将很好地工作,但是如果不释放它,则继续在循环中执行yChange-当然根本不需要这样做。你能帮我这个忙吗?

import React, { Component } from 'react';
import { Input, Upload , Icon, message} from 'antd';
import Form from '../../components/uielements/form';
import Checkbox from '../../components/uielements/checkbox';
import Button from '../../components/uielements/button';
import Notification from '../../components/notification';
import { adalApiFetch } from '../../adalConfig';

const FormItem = Form.Item;

class RegisterTenantForm extends Component {
    constructor(props) {
        super(props);
        this.state = {TenantId: '', TenantUrl: '', CertificatePassword: '', confirmDirty: false, loading: false, buttondisabled: true };
        this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
        this.handleChangeCertificatePassword = this.handleChangeCertificatePassword.bind(this);
        this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleupload = this.handleupload.bind(this);
        this.handleTenantIdValidation = this.handleTenantIdValidation.bind(this);
        this.handleTenantAdminUrl = this.handleTenantAdminUrl.bind(this);

    };

    handleChangeTenantUrl(event){
        this.setState({TenantUrl: event.target.value});
    }

    handleChangeCertificatePassword(event){
        this.setState({CertificatePassword: event.target.value});
    }

    handleChangeTenantId(event){
        this.setState({TenantId: event.target.value});
    }

    beforeUpload(file) {
        const isJPG = file.type === 'image/jpeg';
        if (!isJPG) {
          message.error('You can only upload JPG file!');
        }
    }

    handleupload(info){
        //let files = e.target.files;
        if (info.file.status === 'uploading') {
            this.setState({ loading: true });
            return;
        }

        if (info.file.status === 'done') {
            this.setState({ loading: false });
            this.setState({ 'selectedFile': info.file });
        }

    }

    handleTenantIdValidation(rule, value, callback){
        const form = this.props.form;
        var re = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
        if (!form.getFieldValue('tenantid').match(re)) {
            callback('Tenant id is not correctly formated id');
        } 
        else {
            callback();
        }
    }

    handleTenantAdminUrl(rule, value, callback){
        const form = this.props.form;
        var re = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/i;
        if (!form.getFieldValue('tenantadminurl').match(re)) {
            callback('Tenant Url is not correctly formated id');
        } 
        else {
            callback();
        }
    }


    handleSubmit(e){
        e.preventDefault();
        this.props.form.validateFieldsAndScroll((err, values) => {
            if (!err) {
                /*Notification(
                'success',
                'Received values of form',
                JSON.stringify(values)
                );*/

                let data = new FormData();
                //Append files to form data
                data.append("model", JSON.stringify({ "TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "CertificatePassword": this.state.CertificatePassword }));
                //data.append("model", {"TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "TenantPassword": this.state.TenantPassword });

                let files = this.state.selectedFile;
                for (let i = 0; i < files.length; i++) {
                  data.append("file", files[i], files[i].name);
                }

                const options = {
                  method: 'put',
                  body: data,
                  config: {
                    headers: {
                      'Content-Type': 'multipart/form-data'
                    }
                  }
                };

                adalApiFetch(fetch, "/Tenant", options)
                  .then(response => response.json())
                  .then(responseJson => {
                    if (!this.isCancelled) {
                      this.setState({ data: responseJson });
                    }
                  })
                  .catch(error => {
                    console.error(error);
                });
            }
        });      
    }



    render() {
        const uploadButton = (
            <div>
                <Icon type={this.state.loading ? 'loading' : 'plus'} />
                <div className="ant-upload-text">Upload</div>
            </div>
        );

        const { getFieldDecorator } = this.props.form;

        const formItemLayout = {
        labelCol: {
            xs: { span: 24 },
            sm: { span: 6 },
        },
        wrapperCol: {
            xs: { span: 24 },
            sm: { span: 14 },
        },
        };
        const tailFormItemLayout = {
        wrapperCol: {
            xs: {
            span: 24,
            offset: 0,
            },
            sm: {
            span: 14,
            offset: 6,
            },
        },
        };
        return (
            <Form onSubmit={this.handleSubmit}>
                <FormItem {...formItemLayout} label="Tenant Id" hasFeedback>
                {getFieldDecorator('tenantid', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your tenant id',
                    },
                    {
                        validator: this.handleTenantIdValidation
                    }],
                })(<Input name="tenantid" id="tenantid" onChange={this.handleChangeTenantId}/>)}
                </FormItem>
                <FormItem {...formItemLayout} label="Certificate Password" hasFeedback>
                {getFieldDecorator('certificatepassword', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your password!',
                    }
                    ],
                })(<Input type="password" name="certificatepassword" id="certificatepassword" onChange={this.handleChangeCertificatePassword}/>)}
                </FormItem>
                <FormItem {...formItemLayout} label="Tenant admin url" hasFeedback>
                {getFieldDecorator('tenantadminurl', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your tenant admin url!',
                    },
                    {
                        validator: this.handleTenantAdminUrl
                    }],
                })(<Input name="tenantadminurl" id="tenantadminurl"  onChange={this.handleChangeTenantUrl} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Certificate File">
                    <Upload  onChange={this.handleupload} beforeUpload={this.beforeUpload}>

                        <Button >
                            <Icon type="upload" /> Click to Upload
                        </Button>
                    </Upload>

                </FormItem>
                <FormItem {...tailFormItemLayout}>
                    <Button type="primary" htmlType="submit" disabled={this.state.buttondisabled}>
                        Register tenant
                    </Button>
                </FormItem>
            </Form>
        );
    }
}

const WrappedRegisterTenantForm = Form.create()(RegisterTenantForm);
export default WrappedRegisterTenantForm;

3 个答案:

答案 0 :(得分:3)

如果您只希望播放器每次上压能够跳10个“单位”然后停在原处,则可以在将yChange添加到mainCharY之后,将每帧yChange设置为0。

但是,如果您正在寻找一个更强大的跳跃系统(按下按钮,播放器向上移动几帧,然后停下来然后跌倒),则需要更多。

给您一个想法:如果您在每帧的末尾有一些逻辑来检查mainCharY> 0(玩家不在地面上),并且如果是,则从yChange中减去一些数字(就像重力在拉动)他们下来)?

在上述情况下,您的代码应避免重复按下新闻的问题。仅测试(mainCharY> 0)而不是使用isJumping变量可能会更容易。

答案 1 :(得分:1)

我认为pygame可能根本不会错过关键事件。

我认为问题在于您没有在任何地方将isJumping设置为false,这会在首次按下后永远停止更改yChange。如果我正确地解释了这一点,那么以下代码应该可以工作:

if event.type == pygame.KEYDOWN:
    ...  # Your other code

    if event.key == pygame.K_UP and not isJumping:  # "== False" is not necessary
        yChange -= 10
        isJumping = True


if event.type == pygame.KEYUP:
    ...  # Your other code

    if event.key == pygame.K_UP and isJumping:
        yChange = 0
        isJumping = False  # <-- This is the addition to the code

要记住的一件事是,这种跳跃系统看起来不会很自然。期待@SamHolloway的答案以对此进行更多的澄清。

答案 2 :(得分:1)

似乎您误解了事件队列和事件循环的工作方式。当您按下一个键时,单个pygame.KEYDOWN事件将被添加到事件队列中。调用pygame.event.get将清空事件队列,并将所有事件放入一个列表中,并使用for循环对其进行迭代:for event in pygame.event.get():。这意味着pygame不知道您仍在按住该键,它只会看到您已按下UP一次。它还将注意到您释放了密钥并将一个pygame.KEYUP事件添加到队列中。

在您的情况下,按UP键会将yChange变量减小为-10。在while循环中,mainCharY每帧将减少-10,并且字符将向上移动。释放键后,yChange将重置为0,并且播放器角色将停止。

if event.type == pygame.KEYUP:
    if event.key == pygame.K_UP:
        yChange = 0

要在游戏中实现跳跃,您应该添加一个重力常数,并在每帧的y速度中添加该常数以向下加速。当角色接触地面时,将y速度设置为0,并将变量(on_ground或类似的变量)设置为True,以便您知道玩家可以跳跃。当玩家按下跳转键时,您可以将y速度设置为负值,并且精灵将开始向上移动,直到重力再次将他拉低。这是complete example