Right now, I have a websocket server that sends the client the position of other players using an object ({pos:{x:32,y:46}}). I then put that into a point by doing var newposition = new Point(msg.pos.x,msg.pos.y) but then I never see the player appear.
I tried to console.log it, but it said the position was NaN. Then I tried to console.log the point, and it worked. I even tried not setting the position at all but it randomly sets its position to NaN for no reason that I can see.
This is my code for making a player join:
function addPlayer(nickname,position,color,uid,size,face) {
var circle = new Path.Circle(position,size)
var face = new Raster("/faces/"+face+"/face.png")
face.rescale(40,40)
face.position = position
var masker = new Group({
children: [circle, face],
clipped: true
});
face.onLoad = function() {
// Fit the circle snugly around the image:
circle.fitBounds(face.bounds);
};
circle.fillColor = color
console.log(nickname + " has joined the server")
console.log(players)
players[uid] = {
circle: circle,
nickname: nickname,
entirething: masker,
face: face
}
console.log(circle.position)
}
And here's what happens when a player moves (without actually setting the position of the player.)
if(msg.event == "move" && msg.who != cuid) {
var thepoint = new Point(msg.pos.x,msg.pos.y)
console.log(thepoint)
console.log(players[msg.who].circle.position)
}
And finally when the player joins:
if(msg.event == "join" && msg.who != cuid) {
addPlayer(msg.username,{x:0,y:0},"dodgerblue",msg.who,20,msg.face)
}
On my backend, I just have it broadcast that someone joined with their id (who) and face (face).
There are no errors in the console and I am rather confused of why this happens... Why does it set itself to NaN?
(I put this as an answer rather than as a comment because I won't have enough space there)
In order to find where the problem comes from, try simulating messages coming from the backend, to check that your client-side logic is right.
Here is a sketch adapted from your code sample that can serve as a starting point for this task.
I modified some things that didn't make sense to me but I think that you should be able to adapt it to your specific case.
// Init global variables.
var cuid = 999;
var players = {};
function addPlayer(nickname, position, color, uid, size, face) {
// Init image and circle.
var circle = new Path.Circle(position, size);
var image = new Raster(face);
image.onLoad = function() {
// Make image fit circle bounds.
image.fitBounds(circle.bounds);
};
// Use circle as image clip mask.
var masker = new Group({
children: [circle, image],
clipped: true
});
console.log(nickname + ' has joined the server');
// Store player.
players[uid] = {
circle: circle,
nickname: nickname,
entirething: masker,
face: image
};
}
// On message...
function onMessage(msg) {
// If message concerns current player...
if (msg.who === cuid) {
// ...don't do nothing.
return;
}
// If message is a move event...
else if (msg.event == 'move' && msg.who != cuid) {
// ...update player position.
players[msg.who].entirething.position = new Point(msg.pos.x, msg.pos.y);
// If message is a join event...
} else if (msg.event == 'join' && msg.who != cuid) {
// ...add a new player.
addPlayer(msg.username, { x: 0, y: 0 }, 'dodgerblue', msg.who, 20, msg.face);
}
}
//
// Simulate messages reception.
//
// Add player 1
onMessage({
event: 'join',
who: 1,
username: 'player 1',
face: 'http://assets.paperjs.org/images/marilyn.jpg'
});
// Move player 1
onMessage({
event: 'move',
who: 1,
pos: {
x: 50,
y: 50
}
});
// Add player 2
onMessage({
event: 'join',
who: 2,
username: 'player 2',
face: 'http://assets.paperjs.org/images/marilyn.jpg'
});
// Move player 2
onMessage({
event: 'move',
who: 2,
pos: {
x: 500,
y: 125
}
});
Related
I've been working on a project found here -> https://paperambi.glitch.me/
as seen in console, all my tiles are recorded null, and therefore i cant get their index property, what is wrong with my tiles, and is there anyway to fix it?
Heres an example, when you click on tiles to get properties, its null
and if you add index, it responds with cannot find null of index.
Am I using the wrong function, or have something wrong with my tiles?
code sandbox -> https://codesandbox.io/s/31xpvv85om?hidenavigation=1&module=/js/index.js&moduleview=1&file=/js/index.js:0-3327
all code for the example
/**
* Author: Michael Hadley, mikewesthad.com
* Asset Credits:
* - Tileset by 0x72 under CC-0, https://0x72.itch.io/16x16-industrial-tileset
*/
import Phaser from "phaser";
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: "game-container",
backgroundColor: "#1d212d",
pixelArt: true,
scene: {
preload: preload,
create: create,
update: update
}
};
const game = new Phaser.Game(config);
let controls;
let marker;
let shiftKey;
let groundLayer;
function preload() {
this.load.image(
"tiles",
"../assets/tilesets/0x72-industrial-tileset-32px-extruded.png"
);
this.load.tilemapTiledJSON(
"map",
"../assets/tilemaps/platformer-simple.json"
);
}
function create() {
const map = this.make.tilemap({ key: "map" });
const tiles = map.addTilesetImage(
"0x72-industrial-tileset-32px-extruded",
"tiles"
);
// Same setup as static layers
map.createLayer("Background", tiles);
groundLayer = map.createLayer("Ground", tiles);
map.createLayer("Foreground", tiles);
shiftKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT);
// Set up the arrows to control the camera
const cursors = this.input.keyboard.createCursorKeys();
const controlConfig = {
camera: this.cameras.main,
left: cursors.left,
right: cursors.right,
up: cursors.up,
down: cursors.down,
speed: 0.5
};
controls = new Phaser.Cameras.Controls.FixedKeyControl(controlConfig);
// Limit the camera to the map size
this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
// Create a simple graphic that can be used to show which tile the mouse is over
marker = this.add.graphics();
marker.lineStyle(5, 0xffffff, 1);
marker.strokeRect(0, 0, map.tileWidth, map.tileHeight);
marker.lineStyle(3, 0xff4f78, 1);
marker.strokeRect(0, 0, map.tileWidth, map.tileHeight);
// Help text that has a "fixed" position on the screen
this.add
.text(
16,
16,
"Arrow keys to scroll\nLeft-click to draw tiles\nShift + left-click to erase",
{
font: "18px monospace",
fill: "#000000",
padding: { x: 20, y: 10 },
backgroundColor: "#ffffff"
}
)
.setScrollFactor(0);
}
function update(time, delta) {
controls.update(delta);
// Convert the mouse position to world position within the camera
const worldPoint = this.input.activePointer.positionToCamera(
this.cameras.main
);
// Place the marker in world space, but snap it to the tile grid. If we convert world -> tile and
// then tile -> world, we end up with the position of the tile under the pointer
const pointerTileXY = groundLayer.worldToTileXY(worldPoint.x, worldPoint.y);
const snappedWorldPoint = groundLayer.tileToWorldXY(
pointerTileXY.x,
pointerTileXY.y
);
marker.setPosition(snappedWorldPoint.x, snappedWorldPoint.y);
// Draw or erase tiles (only within the groundLayer)
if (this.input.manager.activePointer.isDown) {
if (shiftKey.isDown) {
groundLayer.removeTileAtWorldXY(worldPoint.x, worldPoint.y);
} else {
groundLayer.putTileAtWorldXY(353, worldPoint.x, worldPoint.y);
var tile = groundLayer.getTileAt(
worldPoint.x,
worldPoint.y
); //.index;
console.log(tile);
}
}
}
The problem is the function you are using getTileAt (link to the documentation), with world coordinates, there are two easy solutions:
you could use your variable pointerTileXY like:
var tile = groundLayer.getTileAt(
pointerTileXY.x,
pointerTileXY.y
);
Or you could use the function getTileAtWorldXY (link to the documentation)
var tile = groundLayer.getTileAtWorldXY(
worldPoint.x,
worldPoint.y
);
I'm creating my own drawer online with mxGraph. I want to make my ConnectionConstraints always visibles on the sheet after the creation of my cell. I tried to edit mxConstraintHandler but it didn't worked. This is what I want, even after the mouse left the shape --> enter image description here. The 'x' on the shape have to be always persistent.
Instead you can try ports. that's Using the isPort hook for visually connecting to another cell. And for 'x' shape use offset of geometry.
Please check Hello Port example
// Program starts here. Creates a sample graph in the
// DOM node with the specified ID. This function is invoked
// from the onLoad event handler of the document (see below).
function main(container)
{
// Checks if the browser is supported
if (!mxClient.isBrowserSupported())
{
// Displays an error message if the browser is not supported.
mxUtils.error('Browser is not supported!', 200, false);
}
else
{
// Creates the graph inside the given container
var graph = new mxGraph(container);
graph.setConnectable(true);
graph.setTooltips(true);
// Sets the default edge style
var style = graph.getStylesheet().getDefaultEdgeStyle();
style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;
// Ports are not used as terminals for edges, they are
// only used to compute the graphical connection point
graph.isPort = function(cell)
{
var geo = this.getCellGeometry(cell);
return (geo != null) ? geo.relative : false;
};
// Implements a tooltip that shows the actual
// source and target of an edge
graph.getTooltipForCell = function(cell)
{
if (this.model.isEdge(cell))
{
return this.convertValueToString(this.model.getTerminal(cell, true)) + ' => ' +
this.convertValueToString(this.model.getTerminal(cell, false))
}
return mxGraph.prototype.getTooltipForCell.apply(this, arguments);
};
// Removes the folding icon and disables any folding
graph.isCellFoldable = function(cell)
{
return false;
};
// Enables rubberband selection
new mxRubberband(graph);
// Gets the default parent for inserting new cells. This
// is normally the first child of the root (ie. layer 0).
var parent = graph.getDefaultParent();
// Adds cells to the model in a single step
graph.getModel().beginUpdate();
try
{
var v1 = graph.insertVertex(parent, null, 'Hello', 20, 80, 80, 30);
v1.setConnectable(false);
var v11 = graph.insertVertex(v1, null, '', 1, 1, 10, 10);
v11.geometry.offset = new mxPoint(-5, -5);
v11.geometry.relative = true;
var v12 = graph.insertVertex(v1, null, '', 1, 0, 10, 10);
v12.geometry.offset = new mxPoint(-5, -5);
v12.geometry.relative = true;
var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
var v3 = graph.insertVertex(parent, null, 'World2', 200, 20, 80, 30);
var e1 = graph.insertEdge(parent, null, '', v11, v2);
var e1 = graph.insertEdge(parent, null, '', v12, v3);
}
finally
{
// Updates the display
graph.getModel().endUpdate();
}
var button = mxUtils.button('View XML', function()
{
var encoder = new mxCodec();
var node = encoder.encode(graph.getModel());
mxUtils.popup(mxUtils.getPrettyXml(node), true);
});
document.body.insertBefore(button, container.nextSibling);
}
};
I'm trying create a diagram like this using JointJS.
However, when I'm adding multiple links between elements, I'm only seeing 1 link show up. How do I go about adding multiple links with automatically adjusted space between them?
This is the code to add the boxes and links. Note that right now I'm just trying to add 3 links between all of the blocks, but I'm only seeing 1 link appear between each.
var steps = [{title: "Step 1"}, {title: "Step 2"}, {title: "Step 3"}];
steps.forEach(function(step, i){
var title = step.title;
var yOffset = i*150 + 50; //offsets first block by 50 in y and all others 150
var xOffset = 60; //offsets all blocks by 60
createBlock(title, xOffset, yOffset, i);
});
var blocks = [];
function createBlock(title, x, y, loc) {
var x = (typeof x !== 'undefined') ? x : 0;
var y = (typeof y !== 'undefined') ? y : 0;
var newBlock = new joint.shapes.html.Element({
position: { x: x, y: y },
size: { width: 170, height: 100 },
label: title,
attrs: {
'.label': {
text: title,
'ref-x': .5,
'ref-y': .4,
fill: '#FFFFFF'
},
}
});
blocks.push(newBlock.id);
graph.addCell(newBlock);
if(blocks.length > 1) {
var link = new joint.shapes.devs.Link({
source: {
id: blocks[loc-1],
},
target: {
id: blocks[loc],
},
});
graph.addCell(link);
var link2 = new joint.shapes.devs.Link({
source: {
id: blocks[loc-1],
},
target: {
id: blocks[loc],
},
});
graph.addCell(link2);
var link3 = new joint.shapes.devs.Link({
source: {
id: blocks[loc-1],
},
target: {
id: blocks[loc],
},
});
graph.addCell(link3);
}
}
all the links are lying on top of each other so you see it as a single one. There is code in the demo of jointjs to see each link in different paths. you could add the below code and see that the links show up in different paths. You will need to change the graph to your graph name in the below three lines
// displaying multiple links between two elements in different paths
function adjustVertices(graph, cell) {
// If the cell is a view, find its model.
cell = cell.model || cell;
if (cell instanceof joint.dia.Element) {
_.chain(graph.getConnectedLinks(cell)).groupBy(function(link) {
// the key of the group is the model id of the link's source or target, but not our cell id.
return _.omit([link.get('source').id, link.get('target').id], cell.id)[0];
}).each(function(group, key) {
// If the member of the group has both source and target model adjust vertices.
if (key !== 'undefined') adjustVertices(graph, _.first(group));
});
return;
}
// The cell is a link. Let's find its source and target models.
var srcId = cell.get('source').id || cell.previous('source').id;
var trgId = cell.get('target').id || cell.previous('target').id;
// If one of the ends is not a model, the link has no siblings.
if (!srcId || !trgId) return;
var siblings = _.filter(graph.getLinks(), function(sibling) {
var _srcId = sibling.get('source').id;
var _trgId = sibling.get('target').id;
return (_srcId === srcId && _trgId === trgId) || (_srcId === trgId && _trgId === srcId);
});
switch (siblings.length) {
case 0:
// The link was removed and had no siblings.
break;
case 1:
// There is only one link between the source and target. No vertices needed.
cell.unset('vertices');
break;
default:
// There is more than one siblings. We need to create vertices.
// First of all we'll find the middle point of the link.
var srcCenter = graph.getCell(srcId).getBBox().center();
var trgCenter = graph.getCell(trgId).getBBox().center();
var midPoint = joint.g.line(srcCenter, trgCenter).midpoint();
// Then find the angle it forms.
var theta = srcCenter.theta(trgCenter);
// This is the maximum distance between links
var gap = 20;
_.each(siblings, function(sibling, index) {
// We want the offset values to be calculated as follows 0, 20, 20, 40, 40, 60, 60 ..
var offset = gap * Math.ceil(index / 2);
// Now we need the vertices to be placed at points which are 'offset' pixels distant
// from the first link and forms a perpendicular angle to it. And as index goes up
// alternate left and right.
//
// ^ odd indexes
// |
// |----> index 0 line (straight line between a source center and a target center.
// |
// v even indexes
var sign = index % 2 ? 1 : -1;
var angle = joint.g.toRad(theta + sign * 90);
// We found the vertex.
var vertex = joint.g.point.fromPolar(offset, angle, midPoint);
sibling.set('vertices', [{ x: vertex.x, y: vertex.y }]);
});
}
};
var myAdjustVertices = _.partial(adjustVertices, graph);
// adjust vertices when a cell is removed or its source/target was changed
graph.on('add remove change:source change:target', myAdjustVertices);
// also when an user stops interacting with an element.
graph.on('cell:pointerup', myAdjustVertices);
The core of the solution lies in the adjustVertices function presented below. It accepts a graph and a cell (link or element). For added convenience, the function accepts cell views as well as models.
If cell is a link, it will find all links with the same source and target and then set vertices on them; we will be calling those related links 'siblings'.
If cell is an element, we execute our function for each distinct (different source and target) link connected to the element.
function adjustVertices(graph, cell) {
// if `cell` is a view, find its model
cell = cell.model || cell;
if (cell instanceof joint.dia.Element) {
// `cell` is an element
_.chain(graph.getConnectedLinks(cell))
.groupBy(function(link) {
// the key of the group is the model id of the link's source or target
// cell id is omitted
return _.omit([link.source().id, link.target().id], cell.id)[0];
})
.each(function(group, key) {
// if the member of the group has both source and target model
// then adjust vertices
if (key !== 'undefined') adjustVertices(graph, _.first(group));
})
.value();
return;
}
// `cell` is a link
// get its source and target model IDs
var sourceId = cell.get('source').id || cell.previous('source').id;
var targetId = cell.get('target').id || cell.previous('target').id;
// if one of the ends is not a model
// (if the link is pinned to paper at a point)
// the link is interpreted as having no siblings
if (!sourceId || !targetId) return;
// identify link siblings
var siblings = _.filter(graph.getLinks(), function(sibling) {
var siblingSourceId = sibling.source().id;
var siblingTargetId = sibling.target().id;
// if source and target are the same
// or if source and target are reversed
return ((siblingSourceId === sourceId) && (siblingTargetId === targetId))
|| ((siblingSourceId === targetId) && (siblingTargetId === sourceId));
});
var numSiblings = siblings.length;
switch (numSiblings) {
case 0: {
// the link has no siblings
break;
} case 1: {
// there is only one link
// no vertices needed
cell.unset('vertices');
break;
} default: {
// there are multiple siblings
// we need to create vertices
// find the middle point of the link
var sourceCenter = graph.getCell(sourceId).getBBox().center();
var targetCenter = graph.getCell(targetId).getBBox().center();
var midPoint = g.Line(sourceCenter, targetCenter).midpoint();
// find the angle of the link
var theta = sourceCenter.theta(targetCenter);
// constant
// the maximum distance between two sibling links
var GAP = 20;
_.each(siblings, function(sibling, index) {
// we want offset values to be calculated as 0, 20, 20, 40, 40, 60, 60 ...
var offset = GAP * Math.ceil(index / 2);
// place the vertices at points which are `offset` pixels perpendicularly away
// from the first link
//
// as index goes up, alternate left and right
//
// ^ odd indices
// |
// |----> index 0 sibling - centerline (between source and target centers)
// |
// v even indices
var sign = ((index % 2) ? 1 : -1);
// to assure symmetry, if there is an even number of siblings
// shift all vertices leftward perpendicularly away from the centerline
if ((numSiblings % 2) === 0) {
offset -= ((GAP / 2) * sign);
}
// make reverse links count the same as non-reverse
var reverse = ((theta < 180) ? 1 : -1);
// we found the vertex
var angle = g.toRad(theta + (sign * reverse * 90));
var vertex = g.Point.fromPolar(offset, angle, midPoint);
// replace vertices array with `vertex`
sibling.vertices([vertex]);
});
}
}
}
We then attach the necessary event listeners (function bindInteractionEvents). The vertices are recalculated anytime the user translates an element - as well as anytime a link is added/removed or has its source or target changed.
function bindInteractionEvents(adjustVertices, graph, paper) {
// bind `graph` to the `adjustVertices` function
var adjustGraphVertices = _.partial(adjustVertices, graph);
// adjust vertices when a cell is removed or its source/target was changed
graph.on('add remove change:source change:target', adjustGraphVertices);
// adjust vertices when the user stops interacting with an element
paper.on('cell:pointerup', adjustGraphVertices);
}
I'm developing a tool to add various sprites to the stage. When I drag an element I'd like to display o bounding box ( a rectangle ) that need to move accordingly to the dragging item.
To handle the drag functionality I'm using a lib called draggable
This is the constructor of every single object I push on the stage:
function createElement(x, y, ass_id)
{
// create our little bunny friend..
bunny = new PIXI.Sprite(textures[ass_id]);
bunny.scale.x = bunny.scale.y = 0.2;
bunny.draggable({
snap: true,
snapTolerance:0,
grid: [ 50, 50 ],
alpha: 0.5,
mousedown: function(data) {
/*var fishBounds = new PIXI.Rectangle(
-fishBoundsPadding,
-fishBoundsPadding,
viewWidth + fishBoundsPadding * 2,
viewHeight + fishBoundsPadding * 2);*/
texture_w = (data.target.texture.width) * data.target.scale.x;
texture_h = (data.target.texture.height) * data.target.scale.y;
// scale = data.target.scale.x;
var box = new PIXI.Graphics();
box.lineStyle(2, 0x666666);
box.drawRect(data.target.position.x, data.target.position.y, texture_w, texture_h);
box.scale.x = box.scale.y = scale;
stage.addChild(box);
data.target.boundingBox = box;
console.log(data.target.boundingBox.position, data.target.position);
},
drag: function(data) {
offset_x = data.boundingBox.position.x;//data.position;
offset_y = data.boundingBox.position.y;
data.boundingBox.position.x = data.position.x;// * data.scale.x;// - offset_x;
data.boundingBox.position.y = data.position.y;// * data.scale.y;// - offset_y;
console.log(stage.children.length , data.boundingBox.position, data.position, data);
},
mouseup: function(data) {
console.log("drop");
stage.removeChild(data.target.boundingBox);
}
});
// move the sprite to its designated position
bunny.position.x = x;
bunny.position.y = y;
elements.push(bunny);
// add it to the stage
stage.addChild(elements[elements.length-1]);
}
now, this works like a charm: when I click the element a bounding box gets created in the correct location, the problem is that when I start drag it around the bounding box get away from the item. I thing that the reason for this might be due to the fact the one item is scaled, wether the other isn't, but since I'm a noob at pixi I really find myself stuck with it.
Ok, I discovered that you can easily and conveniently attach an object to another via the addChild, so it comes out like this:
function createElement(x, y, ass_id)
{
// create our little bunny friend..
bunny = new PIXI.Sprite(textures[ass_id]);
bunny.scale.x = bunny.scale.y = 0.2;
bunny.draggable({
snap: true,
snapTolerance:0,
grid: [ 50, 50 ],
alpha: 0.5,
mousedown: function(data) {
texture_w = (data.target.texture.width);
texture_h = (data.target.texture.height);
var box = new PIXI.Graphics();
box.lineStyle(5, 0x666666);
box.drawRect(0, 0, texture_w, texture_h);
data.target.type = "element";
data.target.addChild(box);
},
drag: function(data) {
},
mouseup: function(data) {
console.log("drop");
for (var i = stage.children.length - 1; i >= 0; i--) {
if((stage.children[i].type) && (stage.children[i].type == "element"))
for (var j = stage.children[i].length - 1; i >= 0; i--) {
console.log('remove boundingBox child here when needed');
}
};
}
});
// move the sprite to its designated position
bunny.position.x = x;
bunny.position.y = y;
elements.push(bunny);
// add it to the stage
stage.addChild(elements[elements.length-1]);
}
this is my jsfiddle : jsfiddle.net/V8eKp/5/show
// START -- MOVE CAMERA
var p = new b2Vec2();
p = (ball.body.GetWorldCenter().x) * physics.scale;
pos.push(p);
var length = pos.length;
var s = (pos[length - 1] - pos[length - 2]); //in pixels
if ((halfwidth < (dw - p)) && (p > halfwidth)) {
ctx.translate(-s, 0);
}
I followed the code in here : http://www.codingowl.com/readblog.php?blogid=128
the rendering of the ball is acting weirdly and slow
i saw this example : http://www.emanueleferonato.com/2010/05/04/following-a-body-with-the-camera-in-box2d-the-smart-way/ but i didn't figure out how he do it he used 3 variables stage,x,y wish are undefined in the code he wrote.
and check out this demo by Impactjs and look how the camera move with the player movement i need this functionality : http://impactjs.com/demos/physics/
please can anyone help me in this
As long as ball.body.GetPosition().x > 48, this.current will start incrementing on each update, right? But your draw() only handles 0, 1 and 2.
Got a (kind of) working fix here: http://jsfiddle.net/u4Mv5/
You already got most of it right, just need a bit of work on the scene change logic.
My logic is, whenever the scene change, remove everything, manually shift the ball back or forward, and completely redraw the new scene.
As we are manually shifting the ball, the canvas does not need to be translated.
Draw and loop code: (Simplified)
draw: function () {
this.clear();
new Body(physics, { name: "Ground" });
ball = new Body(physics, { shape: "circle", x: ballx, y: bally, radius: 0.5 });
switch ( this.current ) {
case 0: // First scene
new Body(physics, { name: "Scene0Wall" });
new Body(physics, { name: "Scene0bricks0" });
new Body(physics, { name: "Scene0bricks1" });
break;
case 1: // Second scene
new Body(physics, { name: "Scene1bricks0" });
break;
case 2: // Third scene
new Body(physics, { name: "Scene2bricks0" });
break;
}
},
update: function () {
ballx = ball.body.GetPosition().x;
bally = ball.body.GetPosition().y;
if ( ballx > scene_width ) {
++this.current;
ballx -= scene_width;
this.draw();
}
if ( ballx < 0 && this.current > 0) {
--this.current;
ballx += scene_width;
this.draw();
}
},
This is also easier on scene layout since each scene's origin is [0,0].
I'm only preserving the balls' position, not its state and velocity, which you should implement. The scene layout (and scene cut off point) should also be adjusted to make sure the ball can continue its journey instead of getting stuck in a block.