I have this code that recieves data (wind direction) from an Arduino and this script that shows a compass with the direction. The compass itself works and the data I recieve is correct. The problem is that there is a "wall" at north, so if the wind direction is NW and changes to NE, it doesnt do NW -> N -> NE, it goes like NW -> W -> SW -> S -> SE -> E -> NE
Is there a way to remove this barrier?
CODE FOR COMPASS ITSELF starts at //Kompass
Compass
var socket = io();
socket.on('data', function (data) {
console.log(data);
function safelyParseJSON(json) {
var parsed
try {
parsed = JSON.parse(json)
} catch (e) {
}
return parsed
}
obj = safelyParseJSON(data);
windSpeed = obj.windSpeed;
windDir = obj.windDir;
windFloat = obj.windFloat;
waterAmount = obj.waterAmount;
//Data i tekstform
// document.getElementById('windSpeed').innerHTML = obj.windSpeed;
document.getElementById('windDir').innerHTML = obj.windDir;
document.getElementById('waterAmount').innerHTML = obj.waterAmount;
// Vind-graf
if (chart.data.labels.length != 15) {
chart.data.labels.push(time);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(windSpeed);
});
}
else {
chart.data.labels.shift();
chart.data.labels.push(time);
chart.data.datasets.forEach((dataset) => {
dataset.data.shift();
dataset.data.push(windSpeed);
});
}
chart.update();
});
//Kompas
am5.ready(function () {
var root = am5.Root.new("chartdiv");
root.setThemes([
am5themes_Animated.new(root)
]);
var compassChart = root.container.children.push(
am5radar.RadarChart.new(root, {
panX: false,
panY: false,
startAngle: -90,
endAngle: 270
})
);
var axisRenderer = am5radar.AxisRendererCircular.new(root, {
strokeOpacity: 1,
strokeWidth: 5,
minGridDistance: 10
});
var axis = compassChart.xAxes.push(
am5xy.ValueAxis.new(root, {
maxDeviation: 0,
min: 0,
max: 360,
strictMinMax: true,
renderer: axisRenderer
})
);
axisRenderer.ticks.template.setAll({
forceHidden: true
});
axisRenderer.grid.template.setAll({
forceHidden: true
});
axisRenderer.labels.template.setAll({
forceHidden: true
})
var handDataItem = axis.makeDataItem({
value: 0
});
var hand = handDataItem.set("bullet", am5xy.AxisBullet.new(root, {
sprite: am5radar.ClockHand.new(root, {
radius: am5.percent(99),
topWidth: 5,
bottomWidth: 20,
})
}));
hand.get("sprite").hand.setAll({
fill: am5.color(0xff0000),
fillOpacity: 1
});
axis.createAxisRange(handDataItem);
handDataItem.get("grid").set("visible", false);
handDataItem.get("tick").set("visible", false);
function createLabel(text, value, tickOpacity) {
var axisDataItem = axis.makeDataItem({ value: value });
axis.createAxisRange(axisDataItem);
var label = axisDataItem.get("label");
label.setAll({
text: text,
forceHidden: false,
inside: true,
radius: 20
});
var tick = axisDataItem
.get("tick")
.setAll({
forceHidden: false,
strokeOpacity: tickOpacity,
length: 12 * tickOpacity,
visible: true,
inside: true
});
}
createLabel("N", 0, 1);
createLabel("NE", 45, 1);
createLabel("E", 90, 1);
createLabel("SE", 135, 1);
createLabel("S", 180, 1);
createLabel("SW", 225, 1);
createLabel("W", 270, 1);
createLabel("NW", 315, 1);
for (var i = 0; i < 360; i = i + 5) {
createLabel("", i, 0.5);
}
setInterval(() => {
handDataItem.animate({
key: "value",
to: Math.round(windFloat),
duration: 500,
easing: am5.ease.out(am5.ease.cubic)
});
}, 500);
});
In my code I want to call the function floor2 if the score is more than or equal to 10, and then the function should be called when the player touches the door.
Currently when the player overlaps with the door it does nothing. I have tried moving the if statement about but doesn't seem to do much. I think it's either the if statement mentioned above or the function floor2 causing the error but its a logic error so can't be too sure on where it's coming from
Here is my code:
<html>
<head>
<meta charset="UTF-8" />
<title>Making your first Phaser 3 Game - Part 7</title>
<script src="//cdn.jsdelivr.net/npm/phaser#3.11.0/dist/phaser.js"></script>
<style type="text/css">
body {
margin: 0;
}
</style>
</head>
<body>
<script type="text/javascript">
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var player;
var platforms;
var cursors;
var score = 0;
var scoreText;
var end;
var game = new Phaser.Game(config);
function preload ()
{
this.load.image('sky', 'assets/l1.png');
this.load.image('ground', 'assets/stone.png');
this.load.image('star', 'assets/wine.png');
this.load.image('bomb', 'assets/skull.png');
this.load.image('door', 'assets/door1.png');
this.load.spritesheet('dude', 'assets/test.png', { frameWidth: 39, frameHeight: 56 });
this.load.spritesheet('dead', 'assets/test2.png', { frameWidth: 39, frameHeight: 38.5 });
this.load.audio("bgm",'assets/constantine.mp3');
this.load.audio("bottle",'assets/bottle.mp3');
}
function create (score)
{
bgm = this.sound.add("bgm", { loop: true});
bgm.volume = 1.5
bgm.play();
bottle = this.sound.add("bottle",{loop:false});
bottle.volume = 0.05;
this.add.image(400, 300, 'sky');
door = this.add.image(50,550,'door');
platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground').setScale(2).refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 1, end: 3 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'turn',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 0 }),
frameRate: 20
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 4, end: 6 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'dead',
frames: this.anims.generateFrameNumbers('dead', { start: 0, end: 1 }),
frameRate: 10,
repeat: -1
});
cursors = this.input.keyboard.createCursorKeys();
this.physics.add.collider(player, platforms);
stars = this.physics.add.group({
key: 'star',
repeat: 11,
setXY: { x: 12, y: 0, stepX: 70 }
});
stars.children.iterate(function (child) {
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
this.physics.add.collider(stars, platforms);
this.physics.add.overlap(player, stars, collectStar, null, this)
scoreText = this.add.text(16, 16, 'score: 0', { fontSize: '32px', fill: '#000' });
bombs = this.physics.add.group();
this.physics.add.collider(bombs, platforms);
this.physics.add.collider(player, bombs, hitBomb, null, this);
if (score >= 10)
{
this.physics.add.overlap(player,door,floor2(score));
}
}
function update ()
{
if (cursors.left.isDown)
{
player.setVelocityX(-160);
player.anims.play('left', true);
}
else if (cursors.right.isDown)
{
player.setVelocityX(160);
player.anims.play('right', true);
}
else
{
player.setVelocityX(0);
player.anims.play('turn');
}
if (cursors.up.isDown && player.body.touching.down)
{
player.setVelocityY(-330);
}
}
function collectStar (player, star)
{
star.disableBody(true, true);
score += 10;
bottle.play();
scoreText.setText('Score: ' + score);
if (stars.countActive(true) === 0)
{
stars.children.iterate(function (child) {
child.enableBody(true, child.x, 0, true, true);
});
var x = (player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
var bomb = bombs.create(x, 16, 'bomb');
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
}
}
function hitBomb (player, bomb)
{
this.physics.pause();
player.setTint(0xff0000);
player.anims.play('dead');
end = this.add.text(300, 300, 'game over', { fontSize: '64px', fill: '#808080' });
gameOver = true;
}
function floor2(score)
{
this.physics.pause()
win = this.add.text(300, 300, 'you win', { fontSize: '64px', fill: '#808080' });
gameOver = true;
}
</script>
</body>
</html>
Here is what the game looks like
In Phaser, the create is run once when the game scene is created.
In your create you're setting up the scene and then checking if the score is 10 or more. The player hasn't played the game yet, so their score will be 0, so this.physics.add.overlap(player,door,floor2(score)); isn't run.
At this point the create function is done, and won't be called again, so it'll never check whether the score is 10 or more, and therefore will never add that overlap call.
There's a number of things you could do instead. A few ideas:
Add a check when collecting bottles (collectStar()).
Add a check in update().
Add a function to handle score changes, and check then.
However you implement it, you'll need to check the score outside of create.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
How to correctly register clip-path so that the line is filled correctly that is, along the line and not from top to bottom as now. The screenshots show an example of filling in. On codepen, you can see the entire svg and see how the animation works (it is controlled by scrolling).
Screenshots:
Screenshot with problem:
Now clip-path its (For all code check codepen):
g.setAttribute('style', `clip-path: polygon(0 0%, 100% 0%, 100% ${progress+0.8}%, 0% ${progress+0.8}%);`)
UPDATE:
Please if you offer a solution show it on my example. Since my problem is specific and most just write without looking completely at the problem on codepen.
For each of your coloured lines, create a path that follows the course of that line back and forth. It's stroke width should be wide enough to cover the line at its widest.
You then use that new line as a <mask> to reveal your colours.
The basic idea is described in my answer to a similar question. That question was about simulating animating handwriting. But the same approach will solve your problem also.
https://stackoverflow.com/a/37787761/1292848
Update
Did you check my codepen before answer?
Yes I did. The technique described there will work perfectly fine for your situation. To prove it, here is my own CodePen:
https://codepen.io/PaulLeBeau/pen/RwNOaZg
This is a proof of concept. I have only created a mask path for a short section of the paths. And to demo the concept, I have used a simple CSS animation, instead of implementing an onscroll handler.
It should be fairly obvious what's happening. You will just need to change your onscroll handler to set the stroke-dashoffset based on how far you have scrolled.
If you don't understand how the stroke-offset effect works to animat a line length, then there are plenty of tutorials all over the web, and here on Stack Overflow. For example, CSS-Tricks has a pretty good one:
https://css-tricks.com/svg-line-animation-works/
I have spent quite some time looking into this (few hours) and it is not so simple to solve. BUT I do have a solution. That said, the solution is also not so simple.
Note, the blue polygon is just there to help explain what shape is being used for the clip-path of the group element <g id="Line_Orange" >
I did not attach this to the scroll event because I needed a way to work on the logic behind the clip-path polygon with the simplest set-up I could get and allow me to start and stop the setInterval() to console.log() out the current x and y values etc. to compute where the turns needed to occur etc.
The full example is here: https://codepen.io/Alexander9111/pen/eYmbajB
And the JavaScript is:
var running = false;
const g = document.querySelector("#Line_Orange");
const g_clone = g.cloneNode(true);
const svg = document.querySelector("svg");
g_clone.id = "Line_Grey";
//svg.appendChild(g_clone);
svg.insertBefore(g_clone, svg.childNodes[0]);
g.setAttribute('clip-path', "polygon(0 0, 0 100, 250 100, 250 0)");
const polygon = document.querySelector("#polygon_mask");
let segment_num = 0;
var temp_arr = [];
var polygon_points_arr = [80, 0, 80, 0];
var polygon_points_str = "80 0 80 0";
const polygon_segments = [
{
n: 0, dir: 1, progress: "y", boost: 1, init_x_y: [80,0], index: [3,5],
points:[80, 0, 80, 250, 250, 250, 250, 0]
},
{
n: 1, dir: 1, progress: "y", boost: 2, init_x_y: [80,100], index: [3,null],
points:[80, 0, 80, 250, 250, 100, 250, 0]
},
{
n: 2, dir: 1, progress: "x", boost: 2, init_x_y: [80,250], index: [4,null],
points:[80, 0, 80, 250, 250, 250, 250, 100, 250, 100, 250, 0]
},
{
n: 3, dir: 1, progress: "x", boost: 1, init_x_y: [250,100], index: [4,6],
points:[80, 0, 80, 250, 450, 250, 450, 100, 250, 100, 250, 0]
},
{
n: 4, dir: 1, progress: "x", boost: 2, init_x_y: [700,100], index: [null,6],
points:[80, 0, 80, 250, 700, 250, 820, 100, 250, 100, 250, 0]
},
{
n: 5, dir: 1, progress: "y", boost: 2, init_x_y: [820,100], index: [null,9],
points:[80, 0, 80, 250, 700, 250, 700, 250, 820, 100, 820, 100, 250, 100, 250, 0]
},
{
n: 6, dir: 1, progress: "y", boost: 1, init_x_y: [820,250], index: [7,9],
points:[80, 0, 80, 250, 700, 250, 700, 250, 820, 100, 820, 100, 250, 100, 250, 0]
},
{
n: 7, dir: 1, progress: "y", boost: 2, init_x_y: [820,600], index: [null,9],
points:[80, 0, 80, 250, 700, 250, 700, 600, 820, 600, 820, 100, 250, 100, 250, 0]
},
{
n: 8, dir: -1, progress: "x", boost: 2, init_x_y: [820,750], index: [null,10],
points:[80, 0, 80, 250, 700, 250, 700, 600, 700, 600, 820, 750, 820, 750, 820, 100, 250, 100, 250, 0]
},
{
n: 9, dir: -1, progress: "x", boost: 1, init_x_y: [700,750], index: [8,10],
points:[80, 0, 80, 250, 700, 250, 700, 600, 700, 600, 820, 750, 820, 750, 820, 100, 250, 100, 250, 0]
},
{
n: 10, dir: -1, progress: "x", boost: 2, init_x_y: [150,600], index: [10,null],
points:[80, 0, 80, 250, 700, 250, 700, 600, 150, 600, 150, 600, 150, 750, 150, 750, 820, 750, 820, 100, 250, 100, 250, 0]
},
{
n: 11, dir: 1, progress: "y", boost: 2, init_x_y: [0,600], index: [11,null],
points:[80, 0, 80, 250, 700, 250, 700, 600, 0, 600, 0, 600, 150, 750, 150, 750, 820, 750, 820, 100, 250, 100, 250, 0]
},
{
n: 12, dir: 1, progress: "y", boost: 1, init_x_y: [0,750], index: [11,13],
points:[80, 0, 80, 250, 700, 250, 700, 600, 0, 600, 0, 600, 150, 750, 150, 750, 820, 750, 820, 100, 250, 100, 250, 0]
}
];
var progressY = 0;
var progressX = 80;
const velocity = 1;
var boost = 1;
var direction = 1;
var timeInterval; //to be started at a later time
function myTimer() {
//console.log(progress);
direction = polygon_segments[segment_num].dir;
polygon_points_arr = polygon_segments[segment_num].points;
//console.log("null == 0", null == 0);
var progress = polygon_segments[segment_num].progress == "x" ? progressX : progressY;
var first_index = polygon_segments[segment_num].index[0];
var second_index = polygon_segments[segment_num].index[1];
if (first_index != null){
polygon_points_arr[first_index] = progress;
}
if (second_index != null){
polygon_points_arr[second_index] = progress;
}
polygon_points_arr.map((child, index) => {
if (index % 2 == 0 && index < polygon_points_arr.length - 1){
return child + ",";
} else {
return child
}
});
temp_arr = polygon_points_arr.map((el, index, arr) => {
if ((index + 1) % 2 == 0 && index < arr.length - 1){
return el + ",";
} else {
return el;
}
});
polygon_points_str = temp_arr.join(" ");
console.log(polygon_points_str);
function incrementAndSetValues(){
segment_num +=1;
boost = polygon_segments[segment_num].boost;
progressX = polygon_segments[segment_num].init_x_y[0];
progressY = polygon_segments[segment_num].init_x_y[1];
}
if (progressY>= 10000) {
clearInterval(timeInterval);
} else {
if (segment_num == 0) {
progressY += (velocity * boost * direction);
if (progressY >= 100) {
incrementAndSetValues()
}
} else if (segment_num == 1){
progressY += (velocity * boost * direction);
if (progressY >= 250) {
incrementAndSetValues()
}
console.log(segment_num);
} else if (segment_num == 2){
progressX += (velocity * boost * direction);
if (progressX >= 250) {
incrementAndSetValues()
}
} else if (segment_num == 3){
progressX += (velocity * boost * direction);
if (progressX >= 700) {
incrementAndSetValues()
}
} else if (segment_num == 4){
progressX += (velocity * boost * direction);
if (progressX >= 820) {
incrementAndSetValues()
}
} else if (segment_num == 5){
progressY += (velocity * boost * direction);
if (progressY >= 250) {
incrementAndSetValues()
}
} else if (segment_num == 6){
progressY += (velocity * boost * direction);
if (progressY >= 600) {
incrementAndSetValues()
}
} else if (segment_num == 7){
progressY += (velocity * boost * direction);
if (progressY >= 750) {
incrementAndSetValues()
}
} else if (segment_num == 8){
progressX += (velocity * boost * direction);
if (progressX <= 700) {
incrementAndSetValues()
}
} else if (segment_num == 9){
progressX += (velocity * boost * direction);
if (progressX <= 150) {
incrementAndSetValues()
}
} else if (segment_num == 10){
progressX += (velocity * boost * direction);
if (progressX <= 0) {
incrementAndSetValues()
}
} else if (segment_num == 11){
progressY += (velocity * boost * direction);
if (progressY >= 750) {
incrementAndSetValues()
}
} else if (segment_num == 12){
progressY += (velocity * boost * direction);
}
}
//console.log(segment_num);
g.setAttribute('clip-path', `polygon(${polygon_points_str})`);
polygon.setAttribute('points', polygon_points_str);
}
function myStopFunction() {
console.log("stop X,Y", progressX, progressY);
document.querySelector("#start").removeAttribute('disabled', true);
document.querySelector("#stop").setAttribute('disabled', true);
clearInterval(timeInterval);
running = false;
}
function myStartFunction() {
timeInterval = setInterval(myTimer, 10);
document.querySelector("#start").setAttribute('disabled', true);
document.querySelector("#stop").removeAttribute('disabled', true);
running = true;
}
document.querySelector("#start").addEventListener('click', myStartFunction);
document.querySelector("#stop").addEventListener('click', myStopFunction);
document.addEventListener('keydown', function(e){
console.log(e.code);
if (e.code == "Enter"){
if (running){
myStopFunction();
} else {
myStartFunction();
}
}
});
document.querySelector("#reset").addEventListener('click', function(){
progressY = 0.00;
progressX = 0.00;
segment_num = 0;
myTimer();
document.querySelector("#start").removeAttribute('disabled', true);
document.querySelector("#stop").removeAttribute('disabled', true);
});
document.addEventListener('DOMContentLoaded',
function(){
const g_grey = document.querySelector("#Line_Grey");
//console.log(g_grey);
const grey_paths = g_grey.querySelectorAll("path, polygon");
for (i = 0; i< grey_paths.length; i++) {
//console.log(grey_paths[i]);
if (grey_paths[i].getAttribute('fill') == "none"){
//do nothing
} else if (grey_paths[i].getAttribute('fill') != "#bbbbbb"){
//must be orange, change to grey
grey_paths[i].setAttribute('fill',"#bbbbbb");
}
}
myTimer();
}, false);
And the most important part of the JavaScript is this array:
const polygon_segments = [
{
n: 0, dir: 1, progress: "y", boost: 1, init_x_y: [80,0], index: [3,5],
points:[80, 0, 80, 250, 250, 250, 250, 0]
}, ...
There is a segment for each segment of the polygon, as it grows and becomes more complex.
This diagram should help explain that a little bit:
And this one, explaining how the polygon increases in the number of points:
there seems to be something wrong with the code, one button has to slow down and one button to speed up when I add this code,
this.downButton = this.add.image(80, 530, 'up-bubble').setInteractive();
this.upButton = this.add.image(230, 530, 'down-bubble').setInteractive();
this.input.on('gameobjectup', function (pointer, gameobject) {
if (gameobject === this.downButton && this.spinSpeed > 0)
{
this.spinSpeed -= 0.1;
}
else if (gameobject === this.upButton && this.spinSpeed < 9.9)
{
this.spinSpeed += 0.1;
}
});
but, when I add this code between generateBalls (), it doesn't work at all, it doesn't work,
generateBalls() {
const hitArea = new Phaser.Geom.Rectangle(0, 0, 32, 32);
const hitAreaCallback = Phaser.Geom.Rectangle.Contains;
const circle = new Phaser.Geom.Circle(400, 300, 220);
const balls = this.add.group(null, {
key: 'balls',
frame: [0, 1, 5],
repeat: 5,
setScale: { x: 3, y: 3 },
hitArea: hitArea,
hitAreaCallback: hitAreaCallback,
});
this.downButton = this.add.image(80, 530, 'up-bubble').setInteractive();
this.upButton = this.add.image(230, 530, 'down-bubble').setInteractive();
this.input.on('gameobjectup', function (pointer, gameobject) {
if (gameobject === this.downButton && this.spinSpeed > 0)
{
this.spinSpeed -= 0.1;
}
else if (gameobject === this.upButton && this.spinSpeed < 9.9)
{
this.spinSpeed += 0.1;
}
});
Phaser.Actions.PlaceOnCircle( balls.getChildren(), circle);
return balls;
}
generateDance() {
this.spinSpeed = 0.003;
return this.tweens.addCounter({
from: 220,
to: 160,
duration: 9000,
delay: 2000,
ease: 'Sine.easeInOut',
repeat: -1,
yoyo: true
});
}
update() {
this.playerEyes.update();
Phaser.Actions.RotateAroundDistance( this.balls.getChildren(), { x: 400, y: 300 }, this.spinSpeed, this.dance.getValue());
}
I took the code from the Phaser 3 example
this is https://phaser.io/examples/v3/view/tweens/tween-time-scale
now both buttons function properly
generateDance() {
this.downButton = this.add.image(230, 530, 'up-bubble').setInteractive();
this.upButton = this.add.image( 80, 530, 'down-bubble').setInteractive();
this.spinSpeed = 0.003;
this.downButton.on ('pointerdown', (event) => {
if (this.spinSpeed < 1) { this.spinSpeed += 0.002; }
});
this.upButton.on('pointerdown', (event) => {
if (this.spinSpeed > 0 ) { this.spinSpeed -= 0.001; }
});
return this.tweens.addCounter({
from: 220,
to: 160,
duration: 9000,
delay: 2000,
ease: 'Sine.easeInOut',
repeat: -1,
yoyo: true
});
}