Hi Chris,
Can’t seem to fix this after-image issue
Here is how you can reproduce the problem:
(I can mail you my sprite sheets)
Create a new project using V-play Game template
Add entity in entities folder Mard.qml
import QtQuick 1.1
import Box2D 1.0
import VPlay 1.0
EntityBase {
id: mard
entityType: "mard"
property int health: 100
signal mardkapunch
signal died
property int score: 0
property alias controller: twoAxisController
property real rightValue: 45
property bool __isRunning: false
property bool __isStanding: true
property bool __isPunching: false
property bool __isFlinching: false
property bool __isLookingRight: true
BoxCollider {
id: collider
categories: Box.Category2
collidesWith: Box.Category1 | Box.Category4 | Box.Category5
bodyType: Body.Dynamic
fixedRotation: true
// balancing settings:
linearDamping: 5.0
// set friction between 0 and 1
friction: 0.6
// restitution is bounciness - dont bounce, because then the state would be changed too often
restitution: 0
density: 8
sleepingAllowed: false
anchors.centerIn: parent
width: 75
height: 92
fixture.onBeginContact: {
// play the collision sound when the box collides with anything, but not if the sound is already playing
if(gameScene.collisionSoundsEnabled && !collisionSound.playing)
collisionSound.play();
collisionParticleEffect.start();
var component = other.parent.parent;
var collidingType = component.owningEntity.entityType;
if(collidingType === "metromen" && !__isPunching) {
health = health-10
updatesprite("flinch");
}
if(health < 1){
died();
}
}
}
TwoAxisController {
id: twoAxisController
onInputActionPressed: keypress(actionName);
inputActionsToKeyCode: {
"up": Qt.Key_Up,
"down": Qt.Key_Down,
"left": Qt.Key_Left,
"right": Qt.Key_Right,
"fire": Qt.Key_Space
}
onXAxisChanged: {
console.debug("xAxis changed to", xAxis)
if(xAxis>0)
__isLookingRight = true;
else if(xAxis<0)
__isLookingRight = false;
}
}
Timer {
id: updateTimer
interval: 60
running: true
repeat: true
onTriggered: {
// this must be done every frame, because the linearVelocity gets reduced because of the damping!
var xAxis = controller.xAxis;
if(xAxis) {
collider.body.linearVelocity.x = xAxis*rightValue;
updatesprite("walk")
}else{
collider.body.linearVelocity.x = 0
updateItemPositionAndRotationImmediately();
updatesprite("stand")
}
}
}
SpriteSequenceFromFile {
id: sprite
filename: "../img/mard-hd.json"
Sprite {
name:"standing"
frameNames: [
"character_hero_rig20001.png"
]
frameRate: 1
mirrorX: !__isLookingRight
}
Sprite {
name:"walking"
frameNames: [
"character_hero_rig20001.png","character_hero_rig20002.png","character_hero_rig20003.png","character_hero_rig20004.png",
"character_hero_rig20005.png","character_hero_rig20006.png","character_hero_rig20007.png","character_hero_rig20008.png",
"character_hero_rig20009.png","character_hero_rig20010.png","character_hero_rig20011.png","character_hero_rig20012.png",
"character_hero_rig20013.png","character_hero_rig20014.png","character_hero_rig20015.png","character_hero_rig20016.png",
"character_hero_rig20017.png","character_hero_rig20018.png","character_hero_rig20019.png","character_hero_rig20020.png",
"character_hero_rig20021.png","character_hero_rig20022.png","character_hero_rig20023.png","character_hero_rig20024.png",
"character_hero_rig20025.png","character_hero_rig20026.png","character_hero_rig20027.png","character_hero_rig20028.png",
"character_hero_rig20029.png","character_hero_rig20030.png","character_hero_rig20031.png","character_hero_rig20032.png"
]
frameRate: 26
mirrorX: !__isLookingRight
}
Sprite {
name:"hit"
frameNames: [
"character_hero_rig20034.png","character_hero_rig20035.png","character_hero_rig20036.png","character_hero_rig20037.png",
"character_hero_rig20038.png","character_hero_rig20039.png","character_hero_rig20040.png","character_hero_rig20041.png",
"character_hero_rig20042.png","character_hero_rig20043.png","character_hero_rig20044.png","character_hero_rig20045.png",
"character_hero_rig20046.png","character_hero_rig20047.png","character_hero_rig20048.png","character_hero_rig20049.png"
]
frameRate: 17
mirrorX: !__isLookingRight
}
Sprite {
name:"punching"
frameNames: [
"character_hero_rig20051.png","character_hero_rig20052.png","character_hero_rig20053.png","character_hero_rig20054.png",
"character_hero_rig20055.png","character_hero_rig20056.png","character_hero_rig20057.png","character_hero_rig20058.png",
"character_hero_rig20059.png","character_hero_rig20060.png","character_hero_rig20061.png","character_hero_rig20062.png",
"character_hero_rig20063.png","character_hero_rig20064.png","character_hero_rig20001.png","character_hero_rig20001.png",
"character_hero_rig20001.png","character_hero_rig20001.png","character_hero_rig20001.png","character_hero_rig20001.png",
"character_hero_rig20001.png","character_hero_rig20001.png","character_hero_rig20001.png"
]
frameRate: 30
mirrorX: !__isLookingRight
loop: false
to: "standing"
}
}
// gets played at a collision
Sound {
id: smack
source: "../snd/yeh kha.wav"
}
// this particle effect is played when colliding with an obstacle
Particle {
id: collisionParticleEffect
positionType: ParticleSystem.Free
//fileName: "SmokeParticle.json"
}
function keypress(actionName)
{
if(actionName==="fire" && !__isFlinching && !__isPunching){
mardkapunch();
updatesprite("punch");
smack.play();
}
}
states: [
State {
name: "stand"
PropertyChanges { target: sprite; goalSprite: standing }
},
State {
name: "walk"
PropertyChanges { target: sprite; goalSprite: walking }
},
State {
name: "punch"
PropertyChanges { target: sprite; goalSprite: walking }
}
]
Timer {
id: changestate
interval: 800
running: false
repeat: false
onTriggered: {
__isPunching = "false";
__isFlinching = "false";
__isStanding = "true";
__isRunning = "false";
}
}
Timer {
id: smooth
interval: 5
running: true
repeat: true
onTriggered: {
mard.updateItemPositionAndRotationImmediately();
}
}
function updatesprite(state)
{
if(!__isPunching && !__isFlinching)
{
if(state==="stand")
{
__isPunching = "false";
__isFlinching = "false";
__isStanding = "true";
__isRunning = "false";
sprite.goalSprite="standing";
}
else if(state==="punch")
{
__isPunching = "true";
__isFlinching = "false";
__isStanding = "false";
__isRunning = "false";
sprite.goalSprite="punching";
changestate.start();
}
else if(state==="flinch")
{
__isPunching = "false";
__isFlinching = "true";
__isStanding = "false";
__isRunning = "false";
sprite.goalSprite="hit";
changestate.start();
}
else if(state==="walk")
{
__isPunching = "false";
__isFlinching = "false";
__isStanding = "false";
__isRunning = "true";
sprite.goalSprite="walking";
}
}
}
}
VPlayGameTemplateScene.qml
import QtQuick 1.1
import VPlay 1.0
import Box2D 1.0 // for using the MouseJoint
Scene {
id: scene
property alias mard: level.mard
width: 480
height: 320
// make these items available to the parent GameWindow as properties
property alias level: level
property alias hud: hud
property alias entityContainer: level
property alias player: level.player
// this flag enables or disables particle effects for the boxes
// it can be toggled from the menu
property bool particlesEnabled: true
property bool collisionSoundsEnabled: true
// always put the scene on the bottom of the GameWindow, when the GameWindow has a different aspect ratio than the scene
sceneAlignmentY: "bottom"
BackgroundMusic {
id: backgroundMusic
source: "snd/bg_raggaman.wav"
// the BackgroundMusic will automatically be played, because the autoPlay property is set to true by default
}
// Custom font loading of ttf fonts
FontLoader {
id: fontHUD
source: "fonts/Anton.ttf"
}
// the MultiResolutionImage automatically selects the -sd, -hd or -hd2 image based on the resolution of the device
MultiResolutionImage {
id:levelBackground
source: "img/background-sd.png" // it doesnt matter if -sd, -hd or -hd2 is chosen here, as it is modified automatically
// use this if the image should be centered, which is the most common case
anchors.centerIn: parent
}
SpriteBatchContainer {}
Keys.forwardTo: mard.controller
// contains the level loader
Level {
id: level
anchors.fill: parent
}
// allows collision detection with pyhsics colliders (BoxColliders, CircleColliders and PolygonColliders)
// it supports 2 modes:
// - for collision testing (set collisionTestingOnlyMode to true for each Body) when the positions get updated manually, e.g. by animations
// - for physics driven games like AngryBirds or this sample game, which is the default setting for a Body
PhysicsWorld {
id: physicsWorld
// this puts it on top of all other items for the physics debug renderer
z: 1
// the logical world is smaller, not containing the hud!
height: parent.height-hud.height
// for physics-based games, this should be set to 60!
updatesPerSecondForPhysics: 60
// make objects fall faster by increasing gravity
gravity.y: -9.81//*3
// this should be increased so it looks good, by default it is set to 1 to save performance
// when it is left at 1, the boxes sometimes "float" into each other
velocityIterations: 5
positionIterations: 5
}
HUD {
id: hud
height: 64
// place it on the top right of the window, not on top of the logical scene
anchors.top: scene.gameWindowAnchorItem.top
anchors.right: scene.gameWindowAnchorItem.right
}
Text {
x: 5
// position it at the top of the window, not on top of the logical scene
anchors.top: scene.gameWindowAnchorItem.top
anchors.topMargin: 5
text: "Created Boxes: " + player.createdEntities
font.family: fontHUD.name
font.pixelSize: 18
color: "white"
}
IngameMenu {
id: ingameMenu
// in the default state, this is invisible
visible: false
anchors.centerIn: parent
}
// the default state will reset all PropertyChanges done below
// so when switching back to state "", the ingameMenu will automatically become invisible!
states: State {
name: "ingameMenu"
PropertyChanges { target: ingameMenu; visible: true}
}
}
Level01.qml
import QtQuick 1.1
import "entities"
Item {
anchors.fill: parent
property alias mard: mard
// these entities will be created when the game launches
Mard{
id:mard
x:50
y:200
}
Wall {
height: 30
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
}
Wall {
width: 20
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
}
Wall {
width: 20
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
}
Level.qml
import QtQuick 1.1
Item {
// this is needed so an alias can be created from the GameWindow
property alias player: player
property alias mard: level.mard
// the player object gets modified in the game
QtObject {
id: player
property int createdEntities: 0
onCreatedEntitiesChanged: {
console.debug("created entities changed to:", createdEntities)
}
}
// in here, different levels could be loaded
Level01 {
id: level
}
}