-
I have not been very sucessful at solving even on a very easy one setting.
try rotate mode, thats very easy, the other modes involving sliding are really hard as it requires you to visualize how the water pipes would end up after your move.
Not sure what OPEN/MUS means on the display ?
Open is displayed in the level selector, before you start a game you are in the level selector. By default only the very first level (of 25) is unlocked (open) in any game difficulty (except random). When you are in level selector you can touch on the left or right side of the screen to select the level and there you'll see the open message or locked message if the level is not unlocked yet (and you can not play it then). MUS is actually MVS shorthand for MOVES it just shows you how many slides and rotates you had done.
The touch areas's are quite narrow. You have to be very careful to ensure you are always at
the edge to make sure the selected movement occurs.yeah they are indeed, but if i make them bigger there is more place for error on touching in the middle for the extra button simulation. On the watch i just press the sides of the screen and works ok.
Very ingenious game. Is the design yours or is this a copy of a classic game ?
No i did not invent the game concept, it is based on the Net and Netslide game from the Simon Tatham's Portable Puzzle Collection, but all the code is my own re-implementation of these two game concepts mixed into one game
-
-
Just to let people know that the game is as good as finished, i just need to test it a bit more. I will do a pull request soon against the main repo, but in the mean time you can already get a development build from my github
or you can test and view the code inside the the emulator (note: viewing options might not work inside the emulator as the rubido.settings.js file will not exist, unless you upload it to storage as well using the emulator -
Hi gordon,
Thats a left over from when having the function compile C Code.
If i used the boardpart variable it did not work with compiled C code, it somehow gotten integer numbers back instead of the objects, but if i always referenced it using
BoardParts.Items[Y][X]
the compiled c code worked fine. Initially i had it using theboardPart
variable but that no longer worked when compiled to C code.The current (new iter) implementation also no longer works when compiled to C Code so i just removed the "compiled" flag but i can indeed use boardPart again now.
Will change it back thanks.
-
Hey gordon,
I managed to implement the background counting of movesleft. I've used the setinterval function todo this. And now we can keep on playing immediatly after a move was done and it will update the movesleft value once it has done calculating them. I just call the GameLoop one more time to verify if it is a winning game and draw the results basically my code looks like this now :
//procedure that starts the movesLeftIter function using an interval to loop over //all pegs function movesLeft() { if(movesLeftTimer) clearInterval(movesLeftTimer); movesLeftCount = 0; pegsLeft = 0; movesLeftX = 0; movesLeftY = 0; movesLeftTimer = setInterval(movesLeftIter, 0); } // procedure that calculates how many moves are possible in the current board state for 1 Peg // we can simply do this by checking all parts and see if they can move to all directions // the canmoveto method in CPegs is does all the checking function movesLeftIter() { //print (BoardParts.Items[Y][X]); // if there is a boardpart on that X,Y Coordinate // check all direction if we can move to that if so increases the movesleft if (BoardParts.Items[movesLeftY][movesLeftX]) { if (BoardParts.Items[movesLeftY][movesLeftX].AnimPhase < 2) { pegsLeft++; movesLeftCount += CPeg_CanMoveTo(BoardParts.Items[movesLeftY][movesLeftX], movesLeftX + 2, movesLeftY, false); movesLeftCount += CPeg_CanMoveTo(BoardParts.Items[movesLeftY][movesLeftX], movesLeftX - 2, movesLeftY, false); movesLeftCount += CPeg_CanMoveTo(BoardParts.Items[movesLeftY][movesLeftX], movesLeftX, movesLeftY - 2, false); movesLeftCount += CPeg_CanMoveTo(BoardParts.Items[movesLeftY][movesLeftX], movesLeftX, movesLeftY + 2, false); movesLeftCount += CPeg_CanMoveTo(BoardParts.Items[movesLeftY][movesLeftX], movesLeftX + 2, movesLeftY - 2, false); movesLeftCount += CPeg_CanMoveTo(BoardParts.Items[movesLeftY][movesLeftX], movesLeftX + 2, movesLeftY + 2, false); movesLeftCount += CPeg_CanMoveTo(BoardParts.Items[movesLeftY][movesLeftX], movesLeftX - 2, movesLeftY + 2, false); movesLeftCount += CPeg_CanMoveTo(BoardParts.Items[movesLeftY][movesLeftX], movesLeftX - 2, movesLeftY - 2, false); } } movesLeftX++; if(movesLeftX == NROFCOLS) { movesLeftY++; if((movesLeftY == NROFROWS) && (movesLeftX == NROFCOLS)) { clearInterval(movesLeftTimer); prevMovesLeftCount = movesLeftCount; prevPegsLeft = pegsLeft; if(GameState == GSGAME) loop(); return; } movesLeftX = 0; } }
and that seems to work fine
-
This looks great! It'd be good to see this in the app loader!
Yes that's my aim, but i'm still working on it, i need to still add some options to make the input rects visible and make theming optional.
Do you think you could come up with a small self-contained example bit of code that you could post up here that runs really slow like you mentioned? It might be we can find a way to make it faster.
I'll have to check but it may not be easy to do this as i used classes and such that are intertwined with the checks
What do you mean by "Moves Left" - does it actually try and run through each move each time to see how many would be needed to finish?
Yes, after each "move" you have done, the game loops through all still available pegs using a double for loop (i have a two dimensional array to represent the playfield). And i have a Peg class which contains a canMoveToPostion function that will check if a certain Peg can move to a postion and return true or false. For each peg it then calls this functions with all possible move location per peg, these are 4 or 8 calls (moves) to that function depending on the difficulty (if diagonals are allowed). It has todo this for each peg on the board and then it will display value, but it also uses that value to determine if the game is over (moves left = 0, like no peg can move anywhere anymore)
this is the current code:
function movesLeft() { "compiled"; let result = 0; pegsLeft = 0; let BoardPart; let Y, X; for (Y = 0; Y < NROFROWS; Y++) { for (X = 0; X < NROFCOLS; X++) { BoardPart = BoardParts.Items[Y][X]; //print (BoardParts.Items[Y][X]); // if there is a boardpart on that X,Y Coordinate // check all direction if we can move to that if so increases the movesleft if (BoardParts.Items[Y][X]) { if (BoardParts.Items[Y][X].AnimPhase < 2) { pegsLeft++; result += CPeg_CanMoveTo(BoardParts.Items[Y][X], X + 2, Y, false); result += CPeg_CanMoveTo(BoardParts.Items[Y][X], X - 2, Y, false); result += CPeg_CanMoveTo(BoardParts.Items[Y][X], X, Y - 2, false); result += CPeg_CanMoveTo(BoardParts.Items[Y][X], X, Y + 2, false); result += CPeg_CanMoveTo(BoardParts.Items[Y][X], X + 2, Y - 2, false); result += CPeg_CanMoveTo(BoardParts.Items[Y][X], X + 2, Y + 2, false); result += CPeg_CanMoveTo(BoardParts.Items[Y][X], X - 2, Y + 2, false); result += CPeg_CanMoveTo(BoardParts.Items[Y][X], X - 2, Y - 2, false); } } } } return result; }
Just a thought but even without using compiled code, if you could split the code up such that it could run as a function that gets called multiple times, you could update the screen immediately, and then run the calculation in the background. If the user interacted with the Bangle to make another move you could just cancel, redraw with the new state and start again.
thats not a bad idea, but i'm not sure how easily i can adapt to this, you see i do a single frame game loop and everything gets done during that single frame as soon as thats over the game is idling, i don't have a loop that keeps getting called. If nothing needs drawing it doesn't do anything at all but i could give it a try by recalling the game loop if the calculation had not finished but i'll need to check how i can actually do this. When you say run the calculation in the background do you refer to something like threads or so ? Is that some special functionality in javascript / bangle ?
-
I'm working on version 0.02. It will have bigger playfield tiles and repositioned screen layout so that things are more viewable on the watch itself. The menu's (atm) will remain the same as well as the little ingame help but during gameplay the playfield will actually be a lot bigger, i went from 10x10 tiles to 16x16 tiles and it makes viewing it on the watch a lot better.
If you can't wait for the release there is a dev version available on my github pagesand here is a small gif to show what i mean
-
if you like to try the new changes you can grab the new (dev) version from here https://joyrider3774.github.io/BangleApps/
-
btw @HughB i started working on my idea of using different size of tiles for the playfield and it's much more visible now on the watch. It seems it will work, but the downside is it will use some more ram. The menu's and help screen and text will remain same size though (otherwise i could not fit everything in the screen), but the playfield / puzzles will actually be bigger in size and easily viewable on the watch (i tried it already)
-
I had a look at the code. Is that C code really running ?
Not sure i understand the question but in the emulator the C code is not running, but if it's not javascript code is used. The C code only compiles when uploading to the watch but not in the emulator. I only made specific parts in C all the rest is basically javascript code running. (see line 1023 for example) USECCODE is set to false when it could not compile the C Code (inside the emulator for example) and based on that boolean flag i either run the C Code or the Javascript version of the function
I think there is maybe a problem with the logic for the state machine for the movement / centre button. In the simulator I can go up, up. left, left. Then Right or bottom wil rotate the tile. So it gets a bit confusing.
I can not reproduce this not on my watch nor in the simulator, so when you play the game and you press the upper parts twice (so the selector moves 2 times up) and then you press the left part of the screen twice (so selector moves 2 times left) and then you press the bottom or Right direction it rotates the tile ? Are you certain you pressed the complete bottom or right parts ? Enabling the inputrect in the options will make sure you press in the correct parts as it shows where you are supposed to touche / click. On the bangle itself you need to touch the screen on the sides. Can you be more specific about what you did exactly so i can reproduce it
Edit: not sure if it matters but i run the emulator in chrome on windows
-
I look forward to your next games. Is this your Rubido game ?
Yes thats the rubido game i'm porting. I made that game about 14-15 years ago, for the gp2x and dingoo handhelds, at the time there did not exist iphones or androids and so or at least i did not have one. The gp2x and dingoo were opensource handhelds and most were running linux and people could develop their own games for the machines. There was an active community around these handhelds with people developing games and emulators and users playing them . if you want something similar today the only thing that comes to mind is the playdate which i also own and made a few games for. I took the source code my old game and again ported it to javascript. It's not that hard to convert SDL c/cpp code to espruino but they do require a lot of changing as you can't constantly refresh the screen on the bangle. So i was checking my old games for games that basically only "acted" when input was done and rubido was another such game so i started porting that game also. I've created another thread in the projects page about it and there is a little gif showing the progress so far
-
I just created a little help video, explaining the game mode and usage of the game on the watch. I recorded it using OBS Studio and the emulator as doing it with the watch was probably not going to work already. The video is available on youtube
-
I created the little help video for waternet and put it on youtube
-
High Hugh,
I'm aware of the small puzzle area but the game is port of my arduboy version of the game which in itself was a port of the gameboy version i initially made. The game screen (including text / menu's) all use the same system for drawing. Basically the screen is divided into 10 by 10 grids (arduboy was 8x8) and i don't give screen positions in my functions but provide grid positions (to that set_xy function). If i increase the size of the tiles for the puzzle area, the size of the text increases as well and i would have less space to "write" something on the screen in for example menu's or so.
Also the game is a port, which means i basically copied original C Code inside the espruino ide and i adapted all (mostly graphics) functions to work with the bangle 2js, i did only minor adaptions to gameplay and so but i did not reposition anything or so. You can see here its basically the same game as my arduboy port but just way more tiny. The arduboy had a 128x64 resolution screen and i did adapt the game for the bangle js2 to use bigger tilesizes so that about 176 pixels in width can be used, but the arduboy had a bigger (physical) screen also so things where more visibly on it.
One way i see i could go around the above mentioned issues is to potentially use separate images for text and puzzle tiles and reorder the puzzle area so that the text on the sides is displayed below the puzzles. I could give that a try eventually but initially i wanted to just do a port that more or less worked :)
I'll probably try to improve it sometime later once i have the rubido game finished at least that game does not have these issues about small area's. I'm also working on another playdate game so not sure when i'll come to it but i will give it a look. I kinda hop from one project to another and sometimes doing multiple projects at once :)
regarding your pointsUsing the whole of the screen, hide widgets, no point in having them on when in a game.
there already is an option to hide the widgets but it does not affect the drawing of the puzzles, it does affect the input rects of where you have to "touch" to simulate the directional movement
move all the settings and options out to a settings app that can be called via the Bangle 2 menu.
That should be possible was not sure this was needed, so i kept it inside the game as thats how the original game mostly had it but i did add extra options for the bangle. I'd have to make sure if i change this that people don't loose their progress though, as the options and level unlocks are all saved in the same file, so i'd probably would need to split it up.
maybe a little video to show how to play each game using the different controls.
have you checked the readme on the app loader page or the ingame help, it contained some information about game rules. But I could try todo a video also but it would probably be recorded using the emulator as i have no easy way to record the watch, i'll see what i can do about this
-
not sure if this is it but process.memory() has a parameter and when omitted the parameter is by default true. The parameter defines if garbage collection should happen when calling process.memory or not. setting it to false won't make it do garbage collection setting it to true or ommitting it makes garbage collection happen. see https://www.espruino.com/ReferenceBANGLEJS#t_l_process_memory
Now as to know where that big part of used memory that gets free'd up by the gc comes from i don't know, i also don't know as to why it happens when running it from ram but not from storage file. Maybe it is related to certain code being in ram but if that would be cleared how can the program still run so not sure. Might also be something that gets loaded initially but is no longer required and the GC when calling process.memory free's it up while with storage file code is read and executed from the storage and it does not load complete code in ram.
-
I started on a 2nd project as well, porting my Rubido game to the bangle js2. Rubdio is a little chinese checkers / solitaire game.
The aim of the game in chinese checkers is to select a peg on the board and jump over another peg to land on an empty spot. When doing this the peg you jumped over will be removed from the board. You need to play the game in such a way that only one peg remains on the board at the end. Depending on the difficulty you had chosen this can be either (only) in the middle of the board or anywhere on the board. Also depending on the difficulty you had chosen you can either jump horizontally and vertically over pegs or diagonally as well.
I made a little gif to show case it. It was initially made with dark theme in mind, but i modified the game to let it use 1 bpp images. Luckily the tiles were 16x16 so they are byte aligned for using the frame option op drawImage
I had a hard time optimizing the game, it does not do full screen redraws, thats way too slow anyway, but it only redraws & clears certain parts. But the issue was not with the drawing i had, but calculating moves left after each move. Initially this took 5 seconds on the bangle js2, with same optimasations i managed to make it 3 seconds. Then i tried compiling certain function to C and reduced the slowness even more it now sits at about 800 - 1000ms after doing a move (including drawing) and i really have no idea how to improve that further. The "compile" statement in the beginning of a function really helps a lot. But i had an issue with arrays & objects with it where the compiler did not report a failure during compilation but the function just did not work as expected, but i managed to solve that by directly using the array to access things instead of returning an object from some other function call.
Anyway without further waiting here is a little preview in the form of a gif
-
Sorry for the delay in replying - this looks awesome! I remember playing a similar game (but where the water keeps moving and you have to arrange the pipes fast enough) a loooong time ago.
yeah i played that game also i think it was called pipe dream and i played that on a very old windows version
https://www.youtube.com/watch?app=desktop&v=DkV8PqlMwNc
this game is actually a reimplementation (coded from scratch) of the net and netslide games of the simon tatham puzzle's collection combined into one game
Thanks for the GitHub pages link - that makes trying it a lot easier! Can't wait to get this in the main repository!
I keep adding things, every day i think i have it finished but somehow i keep finding this to add. Yesterday i found out about the inline C compiler and i added a C counterpart for the random function and level generating part (which is actually a maze). It speeded up level generating quite a lot. I did keep the javascript versions as well so it can still work inside the emulator
I think looking at the animation one thing I see is the puzzle itself looks like it could almost be rendered at twice the size and so a lot easier to look at in some cases (I guess as it gets harder it gets too big though). I'm not sure how easy that'd be to do but it might be quite hard to make the puzzle out on the actual watch though...
Hi yes, but the animation does not show everything. The level's size depends on the difficulty and the animation did not show highest difficulty where the levels take (almost) whole width of the screen. The game (at least this version) was initially made for the gameboy which used 8x8 tilesizes, same for the arduboy port. But for the bangle2js i already made the tilesize 10x10 but i can't make it bigger anymore or i don't have enough room in width. Also all things you see are made up of tiles including the text and menu's so the whole screen is made up of different (10x10) tiles so if i increase tilesize text size increase also and i'd have less space to place text (in the options screen text takes almost whole width of screen already). I did try it already on the watch and its still doable but indeed very tiny
smallest levels:
biggest levels:
-
Last week i worked some more of the game, and i added partial redrawing which made a single (game)loop after input quite a lot faster in the different sections of the game. I also added options to show the input rect so you know all the time where you are supposed to touch the screen for the directional movement in menu's or for the cursor inside the game. Further more i switched to 2bpp palette mode graphics and based on a theming option it will adapt the palette to the foreground and background color of your currently selected theme in the watch. If theming is disabled original (black & white) colors are used. I also added an option to play the game with widgets loaded or not, it does require a restart as i don't know how to undo the call to Bangle.loadWidgets but people can choose there preference now if they want widgets displayed or not. The game adapts its drawing position and input rects based on the Bangle.apprect.
The game is currently around 2600 lines of code, but there are some comments here and there, so it's rather chunky. Below you can see a gif showing the above mentioned theming, input rect and widgets options in action
if you can't wait to test the game i've got a development repo going on github
and if you like to test it on your bangle i also have a github pages going where one could download the current development version on their watch already and try it out
you can also see the code and try it out using the emulator
-
If you do use color palette then it won't adhere to the theme automatically though
i edit the palette with the values from g.theme.fg and g.theme.bg now (if theming option in my game is enabled). this seems to work fine
but if it works paletted then there's a good chance it'll work without - maybe you just needed to store the image inverted?
Initially i had chosen in image convertor 2 bit grey scale and then it did not work correctly, but if i choose 2 bit optimal with a palette it did seem to work fine.
-
I will try 1 bpp. Though I dont understand how 1bpp could accept different 3 bit colours.
with the options i used it was made a white heart with black surrounding it. But in 1bpp pixel mode, those pixels can be replaced with the foreground and background color which you are using via setColor. but the heart will indeed contain only 1 solid color (based on the setcolor call).
Thats what seemed to be happening with me when i tested it.
-
i'm not sure if this would help but i think I've gotten it to work with a workaround when using the following as image
require("heatshrink").decompress(atob("ikUgIJGgPw+E/z/D//8v//8///0//4JCj//wH/+EH/0An/AgP4gEPEINgGg4")
I'm not sure but what i think is that only 1 bbp images can change for and background color. so i had chosen 1 bpp black and white in the convertor i also selected transparancy to color so i basically gotten a mask and compress.
what i think transparency to color does is assign a color to the transparent parts but in case of black and white you get black for transparent and white for non transparent parts (basically like a transparency mask). Since i used 1 bits per pixel image the foreground and background colors are used to draw the image so the setColor function seems to work although you had chosen red for on and blue or green depending on theme when not on (full white is #FFF full black is #000)
and transparency seems to set a transparent color but i use image object with that option as it adds a "transparency" element where you can choose the color index of the palette for which color (index) will be the transparent color, but when i tested sometimes it selected wrong index and i had to find the right color index myself for the transparant part. For example at one point i was using 8 bit images with a WEB palette but i had used Magenta as transparant color, it selected 0 as transparent index but it was actually 248 or so for magenta. But i guess this is normal, the tools can't know which color you used as color key in this case. Eventually i kept changing the transparency color index value (programmatically) until i had found the right index for magenta (as i knew it would probably be in web palette).
i struggle sometimes with the transparency stuff as well with the convertor
-
Hi Gordon,
Thanks for your answers, yeah i figured we had to use vertical tilesheets to make the frame option work and when i tested it, it seemed to work fine initially. I was not aware of the byte alginment initially but yeah figured that might have been the issue after testing a bit.
I did try to change my image to a 2bpp (greyscale) 10x10 image but somehow it was still not working correctly for displaying all frames. imageMetrics does correctly report 126 frames with the 10x1260 image but somehow when i draw them some don't display and i was not sure what was causing that so i kept the 8 bit format for now as that seems to work fine. I don't know why the 2 bits per pixel 10x1260 would not work for displaying certain frames i did not really look into it as i knew the 8 bit ones are working fine. The reason it was working initially with the 1bpp 8x1008 image is that because of the width and height of the images (and a frame 8x8) the frames were also always byte aligned and as soon as i changed it to 10x10x1 they no longer were, i just kept it at 8bpp as then the size (width & height) of a single frame does not matter at all
modifying the tools would be nice, but its fairly easy to edit the height value manually but i'm not sure what you mean with the padding is this to make it work for images & bitdepth where the frames are not byte aligned ? to somehow make them bytealgined for every frame ? That would be nice if people want to use other bitdepths, but i'm guessing 8 bits per pixel will always work fine and now that there is some info about how one could use the frame option and that one can use vertical tilesheets to make frames work it should be fine for now (at least for me). Maybe it might be a nice feature to have for the tools in the long run.
edit: using optimal 2 bit with a color palette does work so i switched to that, then i can also try to make it adhere to the theme
-
Hello,
I received my bangle (2) 2 days ago (friday), and i'm working on porting my waternet game to it.
Waternet is a multiplatform puzzle game written for old consoles and handhelds like Game Boy (Color), Game Gear, Master System, Analogue Pocket and Mega Duck (using the gbdk sdk), playdate (using playdate sdk), old gp2x and dingoo (c++), arduboy, ...
The aim of the game, in any game mode is always to connect all pipes so that water can flow through them from the water point source. How you can accomplish this depends on the game mode. The game has a help section in the main menu where people can always check up on the rules of each game mode. The game will have 375 levels, spread over 3 game mode each with 5 difficulties, so that is 25 levels per difficulty / game mode. There will be also a random difficulty which will generate never ending, random levels for the game mode you had chosen.
I had started porting the game using the emulator before i had received my watch. The game was initially written in C but luckily it seems javascript is kinda similar in syntax and i already have the game more or less running. For control i divided the (touch)screen up in a middle part, the 4 corners and the 4 different sides, so you can basically press those parts of the screen to move up / down / left / right etc in menu's and press the middle of the screen to do an action or make a selection in the menu's. Sound i have replaced with a few simple buzz statements as there is no piezo speaker inside the bangle 2. The game also only reacts or redraws (entire screen currently) when there is input on the touch screen, it does not sit in a constant frame loop. It did initially on the arduboy but this would not work on the bangle 2, so i have made some input functions that simulate the previous input based on the touchscreen input (or the side button) and runs a single frame loop and then waits on input again
Anyway here is a gif showing the game running in the emulator. It is tiny on the device itself but still playable and loading the levels is a lot slower on the device (i added a loading message but in the emulator it loads so fast that you never see it displayed).
-
yeah indeed, on the bangle it works fine for me also i was not aware of that initially, so that makes me less worried. I should test more on the bangle also when running in such things. On the bangle memory remains the same as well for me but not in the emulator. I have not tried a different browser yet. I even went as far and "touched" a 1000 times to see if it would eventually crash in the browser using the emulator and it did, but on the bangle its indeed fine which is a relieve
The game uses a selector which you need to move to the a pipe which you want to rotate or to move over an arrow on sides in case of slide mode. If you need to move the selector 3 times left and 4 times down before reaching the waterpipe you want todo your action on it can be done much quicker by quickly touching the screen 3 times near left edge and then 4 times near bottom edge than when having to swipe 3 times left then swipe 4 times down its faster and feels more natural to me than swiping. Also with swiping you obscure in a lot of case the complete playfield on your screen with your finger, while touching on the sides you can still see a bit of the middle. Touching just feels more natural than swiping to me, i did not want to constantly swipe on the screen to move the selector