qml练习:创建地图玩家并且实现人物移动(2)

上一期我们实现了地图的绘制,本篇文章我们进一步实现人物的移动

1基础的概念流程

首先我们要了解一个游戏运行的机制

游戏运行是一帧一帧运行的,多个帧按照一定的时间间隔串起来就形成了我们眼中的游戏画面

此外我们游戏还需要接受玩家的键盘和鼠标信息,然后进行玩家信息的更新

了解了以上的概念,我们继续实现玩家的移动画面

2实现玩家信息的写入和获取

这里采用tiled的对象层设置一个玩家的信息

然后读取map的信息存储到一个vector中

复制代码
 bool MapLoading::parseObjectLayer(const QJsonObject &layerObj, ObjectLayer &objectLayer) {
        objectLayer.name = layerObj["name"].toString();
        objectLayer.visible = layerObj["visible"].toBool(true); // 默认为可见
        
        // 解析对象数组
        QJsonArray objectsArray = layerObj["objects"].toArray();
        for (const QJsonValue &objectValue : objectsArray) {
            QJsonObject obj = objectValue.toObject();
            MapObject mapObject;
            
            // 解析对象基本属性
            mapObject.id = obj["id"].toInt();
            mapObject.name = obj["name"].toString();
            mapObject.type = obj["type"].toString();
            mapObject.x = obj["x"].toDouble();
            mapObject.y = obj["y"].toDouble();
            mapObject.width = obj["width"].toDouble();
            mapObject.height = obj["height"].toDouble();
            mapObject.gid = obj["gid"].toInt(0); // 如果是图块对象
            mapObject.visible = obj["visible"].toBool(true);
            
            // 解析自定义属性
            if (obj.contains("properties")) {
                QJsonArray propertiesArray = obj["properties"].toArray();
                for (const QJsonValue &propValue : propertiesArray) {
                    QJsonObject propObj = propValue.toObject();
                    QString propName = propObj["name"].toString();
                    QJsonValue propValueData = propObj["value"];
                    mapObject.properties[propName] = propValueData;
                }
            }
            
            objectLayer.objects.append(mapObject);
        }
        
        return true;
    }
 
}

3实现键盘事件的获取

简单的采用键盘事件捕获即可完成

复制代码
void GameRenderer::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_W) {
        m_player->setPosition(m_player->position() + QPointF(0, -10));
    }
    if (event->key() == Qt::Key_A) {
        m_player->setPosition(m_player->position() + QPointF(-10, 0));
    }
    if (event->key() == Qt::Key_S) {
        m_player->setPosition(m_player->position() + QPointF(0, 10));
    }
    if (event->key() == Qt::Key_D) {
        m_player->setPosition(m_player->position() + QPointF(10, 0));
    }
}

4玩家类的实现,预留了一些接口,方便后续实现

复制代码
// Player.h
#ifndef PLAYER_H
#define PLAYER_H

#include <QObject>
#include <QPointF>
#include <QString>
#include <QTimer>

namespace gameTools {

class Player : public QObject
{
    Q_OBJECT
    
    // 基本属性
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(QPointF position READ position WRITE setPosition NOTIFY positionChanged)
    Q_PROPERTY(double direction READ direction WRITE setDirection NOTIFY directionChanged)
    
    // 状态属性
    Q_PROPERTY(int health READ health WRITE setHealth NOTIFY healthChanged)
    Q_PROPERTY(int maxHealth READ maxHealth WRITE setMaxHealth NOTIFY maxHealthChanged)
    Q_PROPERTY(int mana READ mana WRITE setMana NOTIFY manaChanged)
    Q_PROPERTY(int maxMana READ maxMana WRITE setMaxMana NOTIFY maxManaChanged)
    Q_PROPERTY(int level READ level WRITE setLevel NOTIFY levelChanged)
    Q_PROPERTY(int experience READ experience WRITE setExperience NOTIFY experienceChanged)
    
    // 移动相关属性
    Q_PROPERTY(double speed READ speed WRITE setSpeed NOTIFY speedChanged)
    Q_PROPERTY(bool isMoving READ isMoving WRITE setIsMoving NOTIFY isMovingChanged)
    Q_PROPERTY(QString animationState READ animationState NOTIFY animationStateChanged)

public:
    explicit Player(const int x, const int y, QObject *parent = nullptr);
    
    // 基本属性访问器
    QString name() const;
    void setName(const QString &name);
    
    QPointF position() const;
    void setPosition(const QPointF &position);
    
    double direction() const;
    void setDirection(double direction);
    
    // 状态属性访问器
    int health() const;
    void setHealth(int health);
    
    int maxHealth() const;
    void setMaxHealth(int maxHealth);
    
    int mana() const;
    void setMana(int mana);
    
    int maxMana() const;
    void setMaxMana(int maxMana);
    
    int level() const;
    void setLevel(int level);
    
    int experience() const;
    void setExperience(int experience);
    
    // 移动相关访问器
    double speed() const;
    void setSpeed(double speed);
    
    bool isMoving() const;
    void setIsMoving(bool isMoving);
    
    QString animationState() const;
    
    // 游戏逻辑方法
    Q_INVOKABLE void moveTo(const QPointF &targetPosition);
    Q_INVOKABLE void stopMoving();
    Q_INVOKABLE void takeDamage(int damage);
    Q_INVOKABLE void heal(int amount);
    Q_INVOKABLE void addExperience(int exp);
    Q_INVOKABLE bool checkLevelUp();

signals:
    void nameChanged();
    void positionChanged();
    void directionChanged();
    void healthChanged();
    void maxHealthChanged();
    void manaChanged();
    void maxManaChanged();
    void levelChanged();
    void experienceChanged();
    void speedChanged();
    void isMovingChanged();
    void animationStateChanged();
    
    // 游戏事件信号
    void playerMoved(const QPointF &newPosition);
    void playerDamaged(int damage);
    void playerHealed(int amount);
    void playerLevelUp(int newLevel);
    void playerDied();

private slots:
    void updateMovement();

private:
    void updateAnimationState();
    void calculateNextLevelExperience();
    
    QString m_name;
    QPointF m_position;
    double m_direction; // 角度,0-360度
    QPointF m_targetPosition;
    
    int m_health;
    int m_maxHealth;
    int m_mana;
    int m_maxMana;
    int m_level;
    int m_experience;
    int m_nextLevelExperience;
    
    double m_speed;
    bool m_isMoving;
    QString m_animationState;
    
    QTimer *m_movementTimer;
};

} // namespace gameTools

#endif // PLAYER_H

5结果

把上面串联起来就可以得到一个移动的玩家,下一步打算实现玩家在视角的居中以及地图边界的设置,同时添加玩家素材

相关推荐
赴生-1 小时前
C++进阶 异常
开发语言·c++
黄毛火烧雪下1 小时前
Java 核心知识点总结(一)
java·开发语言
其实防守也摸鱼1 小时前
软件安全与漏洞--软件安全编码与防御技术理论题库
开发语言·网络·安全·网络安全·软件安全·软件安全与漏洞
x138702859571 小时前
c语言中srtlen(指针使用计算字符长度)、传值和传址调用
c语言·开发语言·算法·visual studio
iCxhust2 小时前
C#进程管理程序
开发语言·汇编·stm32·单片机·c#·微机原理
Strugglingler2 小时前
【Qt,OpenGL, RHI,Wayland 等概念梳理】
qt·opengl·wayland·rhi·x11·egl·glx
凡人叶枫2 小时前
Effective C++ 条款28:避免使用 handles 指向对象内部
linux·服务器·开发语言·c++·嵌入式开发
努力成为AK大王2 小时前
并发编程的核心挑战、优化方案与核心知识点总结
java·开发语言·数据库
AI 编程助手GPT3 小时前
用 Python 做一个世界杯赛前分析脚本:以巴西 vs 摩洛哥为例
开发语言·网络·人工智能·python·chatgpt
lihao lihao3 小时前
Linux信号
开发语言·c++·算法