这适用于基于QML / C ++拼贴的2d塔防风格游戏
https://github.com/mikeNickaloff/TowerDefense-FullCommand-v2
我决定简单地创建我自己的碰撞检查形式,这非常有效..
但它有一个小问题:
我写的碰撞检查系统非常快速地生成成千上万的页面错误 - 在几分钟内超过100万。
碰撞检查负责处理子弹碰撞。
我想知道是否有人可以帮助我找出设计中导致页面错误大幅增加的根本缺陷。
property Component attackerComponent: Qt.createComponent("src_qml/AttackerVisual.qml");
/* create a dynamic attacker */
function create_atttacker(i_attacker) {
var component;
component = attackerComponent;
if (component.status == Component.Ready) {
var dynamicObject = component.createObject(background, { /* properties here from i_attacker */ });
/* CONNECTIONS FROM DYNAMIC ATTACKER OBJECT TO MAIN.QML */
dynamicObject.show_particles.connect(particleOverlay.customEmit);
dynamicObject.removeAttacker.connect(removeAttacker);
}
}
/* remove an attacker from the game */
function removeAttacker(attackerObject) {
/* mark the tiles that this attacker was on now inactive
so that guns wont continue to shoot at them */
var current_tile = attackerObject.current;
var target_tile = attackerObject.target;
current_tile.isActiveTarget = false;
current_tile.isActiveTarget = false;
/* disconnect the show particles signal from the particle system */
attackerObject.show_particles.disconnect(particleOverlay.customEmit);
/* Remove the attacker from the game's traqcking system */
game.board.removeAttacker(attackerObject);
/* destroy the attacker object */
attackerObject.destroy();
}
/* create a new bullet that can be fired from a Gun Item (gunObj) */
function create_projectile(gunObj, target_x, target_y) {
var projectileComponent =
Qt.createComponent("src_qml/ProjectileVisual.qml");
if (projectileComponent.status == Component.Ready) {
var newObj = projectileComponent.createObject(background, {/* default properties from gunObj */ } );
/* add projectile to magazine for later firing */
gunObj.add_ammo_round(newObj);
}
}
Item {
...
ParallelAnimation {
running: true;
id: anim1
NumberAnimation { property: "x"; ... }
NumberAnimation { property: "y"; ... }
onStopped: {
/* send signal from target_square that the projectile
hit this square */
target_square.projectile_hit(min_damage, max_damage, splash_distance);
}
}
Item {
id: viz
ParallelAnimation {
running: true;
id: anim1
NumberAnimation { property: "x"; ... }
NumberAnimation { property: "y"; ... }
onStopped: {
/* move one square forward along the attacker's path */
current = target;
target = next_path_square();
/* disconnect from old path square so it doesnt send
projectile hit events */
current.projectile_hit.disconnect(projectile_hit);
target.projectile_hit.connect(projectile_hit);
target.isActiveTarget = true;
current.isActiveTarget = false;
}
}
function projectile_hit(min_damage, max_damage, splash_distance) {
/* check if Attacker hasnt been already destroyed */
if (viz) {
/* send signal back to main.qml for particles */
viz.show_particles(endX, endY);
var attackerHealth = attacker.health;
attackerHealth -= (Math.random() * (max_damage - min_damage)) + min_damage;
if (attackerHealth < 1) {
/* send signal back to main.qml to destroy
this attacker */
viz.removeAttacker(attacker);
}
}
一切似乎都运行正常,但每当子弹击中攻击者并摧毁它时,它似乎会导致无限增加的页面错误。
再次感谢您提出的任何建议。如果有任何事情需要更详细地解释,请告诉我。我已经删除了大部分/全部不相关的代码,但没有真正深入解释整个过程的工作原理。
答案 0 :(得分:0)
想出来 - 它与Logic用QML编写的事实或我在问题中发布的文件没有任何关系。
事实是,有太多的大文件要在这里发布所有文件,所以我选择了我认为最有可能成为罪魁祸首的前三部分。
显然最后一切都是因为我有一个C ++ Q_INVOKABLE方法直接绑定到一个属性,该方法的代码涉及一个有点复杂列表的循环生成被转换为QVariant -
解决方案是简单地将属性从MEMBER更改为READ,然后单独保存MEMBER,然后只要QML需要它就返回预先计算的值。
这几乎解决了所有内存问题。
感谢大家的意见
供参考:
在Board.cpp
class Board : public QObject {
Q_OBJECT
/* bad Property at fault */
/* Q_PROPERTY(QVariant attackers READ attackers) */
/* fixed version */
Q_PROPERTY(QVariant attackers MEMBER m_attackers)
public:
Board(QObject *parent = 0 );
/* bad declaration */
/* QVariant attackers() {
QVariant rv;
foreach(Attacker * attacker, this - > m_attacker_hash.values()) {
rv.append(QVariant::fromValue(attacker));
}
return rv;
} */
/* Good declaration */
QVariant m_attackers;
/* One time population of m_attackers */
Q_INVOKABLE bool update_attackers() {
QVariant rv;
foreach(Attacker * attacker, this - > m_attacker_hash.values()) {
rv.append(QVariant::fromValue(attacker));
}
m_attackers = rv;
return true;
}
};
&#13;