I've started trying to make a game with kaboom.js and have come across a problem where the animation for an arrow which flashes isn't playing, it just freeze frames at the first frame. Does anybody know what I'm doing wrong?
The Code
const k = kaboom({
width: 320,
height: 240,
scale: 2,
});
k.loadSprite("selArrow", "sprites/selArrow.png", {
sliceX: 2,
sliceY: 2,
anims: {
main: {
from: 0,
to: 3,
speed: 2,
loop: true}
}});
const selArrow = k.add([
k.sprite("selArrow", {anim: "main"}),
k.pos(50),
k.scale(1.5),
k.origin("center"),
]);
The Spritesheet
Related
I'm making a game with Phaser, and I need to have an animation for the health bar going down dynamically stop on a frame, and I couldn't find any clear documentation on the stopOnFrame() method, or the this.anims.getFrame(index) method, both of which woulden't work. I believe that stopOnFrame accepts a frame object, not a frame number but I coulden't figure out how to get that specific frame, as the getFrame() method returned undefined. If there's something I'm missing, my ideal solution looks something like this:
this.hpBar.play({key: 'damageAnimation', startFrame: this.hp})
this.hpBar.stopOnFrame(this.hpBar.getFrame(this.hp - amountOfDamage))
Thanks for any suggestions, cheers!
PS: I know there's some more nuance to how I would use the animations in forwards and reverse to properly create this effect, the example is purely for demonstration.
Two points, you would have to pass a Phaser.Textures.Frame to the stopOnFrame function, and as far as I know the function getFrame doesn't exist (atleast on the phaser sprite GameObject, as shown in your code).
You can use the function getFrameAt on the Animation object, the index has to be here only a valid integer, in the range from 0 - to max frame of the animation.
(btw.: here is the link to the documenation of the stopOnFrame function)
Info: the frame index-count, is based on the frames of the specific animation, not the frame in the spritesheet. (In this example the sprite frame index of the kick is 12, but in the kick animation the index for that specific frame is 2)
Here a Demo:
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
scene: {
preload,
create
}
};
function preload(){
this.load.spritesheet('brawler',
'http://labs.phaser.io/assets/animations/brawler48x48.png',
{ frameWidth: 48, frameHeight: 48 }
);
this.load.image('brawler-sheet',
'http://labs.phaser.io/assets/animations/brawler48x48.png');
}
function create () {
this.add.text(10,10, 'Click, to Stop on kick (third frame)')
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
this.anims.create({
key: 'kick',
frames: this.anims.generateFrameNumbers('brawler',
{ frames: [ 10, 11, 12, 13, 10 ] }),
frameRate: 8,
repeat: -1,
repeatDelay: 0
});
this.add.image(140, 20, 'brawler-sheet')
.setOrigin(0)
const cody = this.add.sprite(100, 90);
cody.setScale(3);
cody.play('kick');
this.input.on('pointerdown', () => {
cody.stopOnFrame(cody.anims.currentAnim.getFrameAt(2))
});
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
But for a simple healt-bar, I would use a phaser tween, not an animation, like this you can set the value more precise, you can easily update the max-health and "animation" is easy.
Here a demo how I would do it (two visula alternatives):
(I would opt for the second version, if you have some nice heart images or so, I could find a better image for the demo)
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
scene: {
create,
preload
},
banner: false
};
function preload ()
{
this.load.image('mushroom',
'https://labs.phaser.io/assets/sprites/mushroom16x16.png');
}
let healthMax = 32*5
function create () {
this.add.text(10,10, 'Click, to animate healthbar')
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
this.healthbarBG = this.add.rectangle(10, 50, 32*5, 10, 0xffffff)
.setOrigin(0);
this.healthbar = this.add.rectangle(12, 52, healthMax - 4, 10 - 4, 0xff0000)
.setOrigin(0);
this.add.text(10, 75, 'Or abit more flashy')
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
let tilespriteBG = this.add.tileSprite(10, 100, 16*5, 16, 'mushroom')
.setOrigin(0)
.setScale(2);
tilespriteBG.setTint(0x2a2a2a)
let tilesprite = this.add.tileSprite(10, 100, 16*5, 16, 'mushroom')
.setOrigin(0)
.setScale(2);
this.input.on('pointerdown', () => {
// remove 50% health
let newHealthWidth = healthMax * .5;
this.tweens.add({
targets: this.healthbar,
width: newHealthWidth,
duration: 750,
ease: 'Power2',
/* this two following properties must be remove, just for demo
yoyo: true,
repeat:-1*/
});
this.tweens.add({
targets: tilesprite,
width: { to: 16 * 5 * .5, from: 16 * 5},
duration: 750,
/* this two following properties must be remove, just for demo
yoyo:true,
repeat:-1*/
});
})
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
modifying the ease and/or the duration property (and others), you can make the animation suitable (and spicy) for the most usecases.
I have 2 keyframe animation variants and when I switch between them I want it to happen with the transition. How can I make it transition all the props when switched from one keyframe animation to another (currently it happens instantly)?
const variants = {
...,
horizontalWiggle: {
x: ["40px", "80px"],
y: [0, 0],
transition: { duration: 0.5, yoyo: Infinity }
},
verticalWiggle: {
x: [0, 0],
y: ["8px", "40px"],
transition: { duration: 0.5, yoyo: Infinity }
}
}
Using with framer motion as so:
<motion.div
className="wiggle"
variants={variations}
initial="init"
animate={vertical ? "verticalWiggle" : "horizontalWiggle"}
/>
Link to the sandbox: https://codesandbox.io/s/long-surf-405lho?file=/src/App.js
You have two options:
You should not specify 0 for axis which you do not want to animate. That way there will be no instant jump and will be smooth animation between variants.
The idea is start new animation (new variant) from last position of previous variant. Another words: you need to stop old animation and start new animation from the same value (the same keyframe). That way there also will be no instant jump.
Full example here:
NOTE: if you need to animate between variants - you could create one more variant with animation from STATE-1 to STATE-2.
Like here:
Short Example:
const variations = {
...
horizontalWiggle: {
x: [0, 40, 80, 0],
transition: { duration: 1, repeat: Infinity }
},
verticalWiggle: {
y: ["0px", "20px", "40px", "0px"],
transition: { duration: 1, repeat: Infinity }
}
};
Ok, here's my problem, I'm actually reading a json file in my local html file to make an animation.
The animation works pretty well on chrome, mozilla and safari (even if it's lagging a bit on safari but i think it's because my mac is old but nvm).
So here it's what i want, I created an ios app, the app is what i'm using to create the json and i wanted to be able to see the animation from the json in the app.
So i created an WKWebView that allows me to see my web page and here's the problem.
During the animation on my ipad, if i press the plotly animation, points that was here at the moment stay till i reload the web page. Moreover, this is also happening when i enter a number in the field i created that allows me to change the speed animation (a litlle thing that just increase my index by the number entered)
So Here's my webView code (even if i don't think the problem comes from there):
import UIKit
import WebKit
class WebViewVC: UIViewController {
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "test", withExtension: "html")
let myRequest = NSURLRequest(url: url!)
webView.load(myRequest as URLRequest)
}
#IBAction func leaveButtonPressed(){
let menuVC = self.storyboard?.instantiateViewController(withIdentifier: "MenuVC") as! MenuVC
menuVC.modalPresentationStyle = .fullScreen
self.present(menuVC, animated: true, completion: nil)
}
}
and here a part of my plotly js code:
function createDico(i) {
return {
x: [i],
y: [i],
z: [i],
mode: 'markers',
marker: {
size: 12,
line: {
color: 'rgba(217, 217, 217, 0.14)',
width: 0.5
},
opacity: 0.8
},
type: 'scatter3d'
};
}
function setDatas() {
for (const [key] of datas[0]) {
if (key != 'bodyOrientation') {
joints[key] = createDico(0)
}
}
var data = getDataStep(0)
console.log(data)
var layout = {
margin: {
l: 0,
r: 0,
b: 0,
t: 100,
},
scene: {
xaxis: {
range: [xMin - 3, xMax + 3],
},
yaxis: {
range: [yMin - 3, yMax + 3],
},
zaxis: {
range: [zMin - 0.5, zMax + 0.5],
},
aspectratio: {
x: 1,
y: 1,
z: 1
},
width: 1000,
},
autoexpand: false,
title: {
text: "jsonPlot",
xanchor: "center"
},
width: 700,
height: 500,
autosize: false
};
Plotly.newPlot('myDiv', data, layout);
}
And i don't even know where the problem comes from so i'm not able to solve anything :/
I'm trying to loop an animation with the Framer Motion library after a small delay. The animation itself will play when it's mounted, on the webpage refresh, however does not repeat.
Iv'e looked through the docs and this seems to be similar syntax.
const AnimateTrial = {
initial: {
opacity: 0,
x: -100,
y: -35,
scale: 0.9,
},
animate: (i) => {
const delay = 5 + i * 0.5;
return {
opacity: 1,
x: -10,
y: -35,
transition: {
opacity: { delay, duration: 1.5 },
x: { delay, duration: 1.5},
repeatType: "Infinity",
repeatDelay: 5,
},
};
}
Does anyone have an idea? Everything works minus bottom two lines!
The properties inside your transition object are not right. Use repeat in place of repeatType, Write it something like this
transition={{ repeat: Infinity, repeatDelay: 5 }}
If you check the docs repeateType property accepts only "loop" "reverse" "mirror" and not "Infinity".
I am building a website that has some parallax on the site. Below is what the console says is in the javascript file. I keep getting cannot read data destroy property, because the program has nothing to delete. The picture at the bottom is what I wrote vs what showed up? This is bootstrap studio and I was wondering if anyone has had this problem before?
window.addEventListener("resize", colReset);
let col = document.querySelectorAll(".col-xxl-6");
function colReset() {
window.matchMedia("(min-width: 992px)").matches ? VanillaTilt.init(col, {
max: 15,
speed: 400,
perspective: 750,
scale: 1.005
}) : col.vanillaTilt.destroy()
}
VanillaTilt.init(col, {
max: 15,
speed: 400,
perspective: 750,
scale: 1.005
});