The lack of movement ability of the object in one direction but the ability to move in the opposite direction in abacus

Hello and thank you, very clicking and having the x and y coordinates of four beads in different modes, you can limit the movement between two objects, but we want to do this by this:

With dragging(my question)

With clicking(you made):

Suggest applying drag method to each ball, but avoid collisions by using X locations as targets for each sprite. Issue may be that the balls are too close together anyway for fat fingers to accurately select them?

1 Like


barkhord.aia (75.8 KB)

This seems to work reasonably well

abacusVert.aia (104.1 KB)

1 Like

I drew on my experience riding the NYC subways at rush hour to develop this:

Sample run
subwayPush.aia (106.5 KB)

The idea is to add lists of sprite components to act as tracks, with disabled tiny sprites at each end of each track, to act as stoppers.

Before each sprite responds to a drag, it must check the gap between it and its neighbor in that drag direction, and shove that neighbor a minimal distance to allow room for the current sprite's drag.

The procedures are recursive, like the chain of pushing needed to crowd into a subway car.

(Thanks to @TimAI2 for the Sprites)
(Thanks to @mah_bagh for a fun problem)

Detailed explanation:

The Tokyo subway image is a little misleading. AI2 sprites are inelastic, compared to subway passengers, so they don't transfer force according to Hooke's Law.

What is being transferred from passenger to passenger (sprite to sprite) is a polite request:

Could you please move dY pixels in this direction, if you don't mind, and if you have the space to do so?

(dY is short for delta Y, math speak for a difference between two Y values. It's Y values because the sprites move up and down in this example.)

The Sprites are lined up along a line on a Canvas:

(See further posts in this thread, to give the board a chance to catch up.)


Hello and thanks, it was very interesting and excellent. It was also very interesting to get the idea from the subway :rosette: :grinning:
Please, if possible, write us explanations about the blocks.

Hello again, if we have another canvas with another row of four beads, how do the codes change?thanks

They should be the same, each canvas is sandboxed, but you need to ensure you name your imageSprites per canvas, e.g. for Canvas1, start all your imageSprites with the prefix can1-

1 Like

In that case, the list of beads would have to be passed as a parameter to the move procedure.

For an abacus, you would probably need to keep a list of tracks.

In that case, you would benefit from a value procedure that accepts a sprite component and looks up its track in that list of tracks.

1 Like

Notice the colors of the sprites in their order on the Canvas, compared to their names on the global track list. They match, give or take the two extra tiny (1 px by 1 px) inactive wall sprites I added as stoppers.

The order of the sprite components in the Designer's component tree can't be adjusted, so we work from the Y positions of the sprites in building our list by hand in the Blocks Editor.

1 Like

In this Project, I apply Sprite Cannibalization Prevention to make sure only one Sprite gets dragged at a time.

To do that, I need a global variable touched to remember which Sprite I started to drag.
initialize global touched to

when any ImageSprite.TouchUp   component   notAlreadyHandled   x   y   do

I use that variable in the drag event to make sure only the one Sprite gets dragged.

The three way AND test covers three possibilities:

  • Defer to any other drag event blocks for other sprites that might not benefit from this logic
  • Only drag the sprite that was touched last (see above)
  • only drag an active sprite

To simplify the logic, check the current and previous Y values of this drag event, to see whether its an upward or downward drag, and call the appropriate procedure with a positive value for dY to simplify things.

(We don't have any horizontal tracks, so we work only in Y coordinates.)

1 Like

This value procedure returns a non-negative number of pixels distance between two sprites on the same track, an upper (smaller Y) sprite and a lower (greater Y) sprite.

Remember, Y starts from the top of the Canvas and increases downwards.

For vertically stacked sprites, the Height of the upper sprite takes away room from the distance between the two sprites' Y values.

1 Like

This procedure asks a sprite to move downward (increasing Y) on the global track.

We first check if dY > 0. That would eliminate 0 movement.
We also avoid the dead wall sprites at the ends of the track.

Local lowerNeighbor is the next sprite down on the track, by index.
This is where paying attention to track order is paying off.

We do a pre-check of the gap between us and the downstairs neighbor.
If it is short, we ask the downstairs neighbor to make up the difference by moving, with a pushDown call to expand the gap a little.

After control returns from the pushDown call for the downstairs neighbor,

We then recalculate the gap, and move ourselves downwards whatever we can manage, the smaller of the new gap or the dY value.

1 Like

Moving upwards uses similar logic to moving downwards, except our neighbor on the track is earlier in the list, and we calculate the gap differently between sprites.

1 Like

Hello again, if possible ،please complete the blocks of .aia file for me to activate the second column of beads . Thank you
abacus_two coloumn.aia (204.7 KB)

I took a look at How to Use an Abacus (with Pictures) - wikiHow
to refresh my memory of how an abacus works, and I think this whole
approach is too superficial, concentrating too much on individual bead physics and not enough on the underlying logical model.

There are only a small number of possible configurations of beads on each wire (2 on a short top wire), and 5 on a longer bottom wire.

The transitions between configurations can be triggered by a single touch to a bead. That touched bead and all the beads between it and the empty center of the track should move to the opposite end of the track, adjacent to any beads already on that end of the track.

Knowing the number of beads at each end allows you to check the math of whoever is manipulating the beads. It also allows you to directly move the Sprites on each wire to their proper coordinates, based on the underlying bead counts and Sprite and Canvas dimensions. It also obviates the need for stopper sprites.

In fact, you could do this with stacks of Buttons, changing the background image of each button to show either an empty stretch of wire or a bead. The lower wire would need 9 buttons (for alignment purposes), and the top wire two buttons.

Another alternative would be to grab 5 images from that abacus web site, representing the 5 possible states of a lower wire, and use those as alternative background images of one Canvas per wire. Then you would not need any Sprites at all, only depending on your knowledge of which of the 5 background images is in place and how far down the Canvas Touch happened.






1 Like

Hi .thanks.
AbaPlayer.aia (211.8 KB)

In a race to the bottom, here is an example of using buttons for a single abacus track, including counting and sound effect!

abacusButtonLogic.aia (11.4 KB)

1 Like

Hello, thank you. It's a good idea (using the background change of beads). Of course, this can be done by clicking and we wanted to do it with drag.

I repeated the two-procedure (bush-up and bush-down )and put the new bead names in a new list and put them in the new two-procedure(ABG power user .aia file above).
I created two new push-up and push-down procedures for each column of beads.
And the second column was also activated by drag.

1 Like