I was having a little fun with making my current 'sudoku' based avatar (and the previous one). It was rather time consuming though, and sometimes error prone. I came up with the idea to code a small version of a sudoku player to automate some of that. (instead of just using ms paint to fill the cells manually by copy & pasting the bitmap)
This is the first step towards that goal...
A 127x127 sudoku grid is dislayed in the client area of the main window.
During real game play, the user would fill in a value into an open 'cell' then click on 'Print Frame' to capture the current frame and save it to a sequentially numbered bitmap file.
This is done for each empty cell on the grid, until the board is completely filled.
The folder with the sequentially numbered files will then be opened in Image Ready to make the animated .gif. I do it in this way because I do not know (yet!) how to do that conversion programmatically. (I briefly looked into doing that, it won't be easy... )
code is attached.
This is in the 'Game Development' board because once it is finished, it will be a playable sudoku game (A tiny one) This is only the start of the code, just an empty sudoku grid at this time. (no cells filled yet with values)
A 'work-in-progress' as I am modifying existing code to work in this new project. I will post updates here as the project progresses... and I have time to devote to it... :smiley:
This is the program Window (currently) the output is a 127x127 bitmap image(s), images will be sequential starting at "00.bmp" once I add the code to do that.
(https://i.postimg.cc/F13BFRFV/00.png) (https://postimg.cc/F13BFRFV)
I hate how PostImg shrinks (slightly) this image, but leaves others alone... click image to view full size
Latest version attached here
Very nice :thumbsup:
I found a library that might be just what I need for converting a series of bitmaps to animated .gif
imagemagick libraries (https://imagemagick.org/script/develop.php)
Of course they don't list x86 assembly, but the C version should work. I will investigate this later for possible incorporation into the project.
I have not downloaded yet. If it is a bloated library or has too many dependencies, I may not use it though.
I will see when I'm back at my computer...
Later...
Hmmm... no .lib files, only C sources (headers, structures, etc) that need to be compiled. :sad:
Seems I will not use that after all. I will (probably way in the future) write the code to make the animated .gif. I have already been looking at some reference material to do just that.
Nice project :thumbsup:
Biterider
Thanks Biterider, jj2007.
After thinking about it for a bit, I think I should make the user interface probably twice as large or a little more.
There will be at least one more menu item on the menu bar, possibly two more.
I just made it in its current form for the initial demo.
Now time to start working on the code. :biggrin: Will probably post updated code, some time within the next few hours or so, time permitting.
Hi,
Well, interesting project. I looked at the posted code,
and it looks as if you just produce 127x127 pixel "frames".
Animated GIFs allow for smaller images to be overlayed onto
an existing image. You might consider making nine 13x13
pixel images and placing them one by one to make your final
animated sequence. Or, of course, I may have misread your
code?
Regards,
Steve N.
Edit: 128 => 127
Hi FORTRANS, if you look at my avatar it has 57 frames. It starts with a grid with 24 clues. Each value is placed one by one, in subsequent frames. Hence, 57 frames. (127x127)
I use ImageReady to assemble the sequence of bitmaps into an optimized GIF, since I do not know (yet) how to do that in code.
Quote from: sudoku on April 30, 2024, 10:08:36 PMHi FORTRANS, if you look at my avatar it has 57 frames. It starts with a grid with 24 clues. Each value is placed one by one, in subsequent frames. Hence, 57 frames. (127x127)
I use ImageReady to assemble the sequence of bitmaps into an optimized GIF, since I do not know (yet) how to do that in code.
I think GDI+ @Microsoft Learn documentation will help you to do you avatar with code.
Quote from: C3 on April 30, 2024, 10:19:54 PMI think GDI+ @Microsoft Learn documentation will help you to do you avatar with code.
Thanks, C3. I have been doing some research on this already, including reading related topics at MS Learn. :smiley:
Perhaps you could use EMF for temporary storage format to save every frame, as it can used to scale quite easily for later usage.
Later GDI+ could save them in usable bitmap format for GIF.
Hi,
Quote from: sudoku on April 30, 2024, 10:08:36 PMHi FORTRANS, if you look at my avatar it has 57 frames. It starts with a grid with 24 clues. Each value is placed one by one, in subsequent frames. Hence, 57 frames. (127x127)
Right, but if you followed my suggestion, you would still have
57 images. One 127x127 and 56 13x13. Just a different way of doing
things.
QuoteI use ImageReady to assemble the sequence of bitmaps into an optimized GIF, since I do not know (yet) how to do that in code.
Well, I wrote my own programs to play around with animated GIFs.
Probably of no interest as they are MS-DOS programs. And looking at
them today, a rather opaque coding style. Amazing what you (I) can
forget about something made a while back. Hash tables, wow.
Cheers,
Steve N.
Quote from: FORTRANS on May 01, 2024, 01:06:04 AMHi,
...
Right, but if you followed my suggestion, you would still have
57 images. One 127x127 and 56 13x13. Just a different way of doing
things.
:thumbsup:
Not a big matter, as ImageReady is doing the heavy lifting. The sequence of bitmaps produced are only needed for a short time until the animated GIF is made, then the sequence of bitmaps discarded. I plan on (attempting at least), creating an animated GIF in code, at some point in the future.
Latest (and earlier) versions work fine here on Windows 7+10 :thumbsup:
Quote from: learn64bit on May 01, 2024, 01:16:55 AMyes. your .exe same symptoms here, haha
Quote from: learn64bit on May 01, 2024, 01:16:55 AMOooops, I broked my win7
Yes, problems with your computer. :thumbsup: ...haha
Progress is a little slower than I had hoped. I am not going to reuse existing code (too time consuming and can introduce bugs) as I first planned but write the funtions for this from scratch.
Anyway I now have implemented cell selection.
click anywhere with the game board to 'select' a cell. Clicking outside of the game board removes the selection.
I have also coded for the sequential file naming. When capturing the game board the first capture is always "00.bmp"...
First file is "00.bmp"
second is "01.bmp"
third "02.bmp" and so forth...
I have also made the window a bit bigger (will need space for a couple more menu items)
(https://i.postimg.cc/XGHGL4Mc/untitled.png) (https://postimg.cc/XGHGL4Mc)
latest version attached in post #1
Added puzzle file loading and keyboard presses.
If a wrong value is entered, the background for the cell turns red indicating error.
Still a work in progress, a lot more work to be done.
(https://i.postimg.cc/1fX2b9bV/untitled.png) (https://postimg.cc/1fX2b9bV)
In the current menu, there is "Reset Game". Actually to reset the game, simply reload it. I will put "Undo Last"(move) in its place, to undo the last move if an invalid move was flagged (red background).
Also right now the solution is hard coded, I may put a simple 'validator' in it to check for valid moves, instead of keeping the solution lying around.
latest version attached in post #1
I am currently playing around with testing "autoprint" to generate the bitmap automatically when a digit is placed - bypassing the need to click "Print Frame" for each frame. It needs a couple more tweaks... (currently also captures the 'selection' bg color which I don't particularly like)
latest version attached in post #1
Further notes...
Originally if a given digit is invalid in a cell, I allowed placing it but colored the background of the invalid cell red. Instead I will disallow placing an invalid digit into a cell. For normal game play, the red bg is okay, but since I am using the program to make bitmap frames for an avatar I will make the program more optimal for that need.
Once I have the program optimized for creating my avatars, I will release a playable version with some features that are better suited for playing the game of sudoku. (Time permitting, of course)
Tried v3, clicking selected a cell but pressing keys did nothing, and the Load menu just blacked out the whole grid then crashed.
Faulting application name: lil_sudoku.exe, version: 0.0.0.0, time stamp: 0x66331c31
Faulting module name: USER32.dll, version: 10.0.22621.3447, time stamp: 0x1cb963cd
Exception code: 0xc000041d
Fault offset: 0x0002eb76
I'll rebuild it as debug and see what triggers it.
You might be having trouble with EDX here
lea edx, [ecx+eax]
invoke SetBkMode, DC, TRANSPARENT
invoke DrawText, DC, addr str1, 1, edx, DT_CENTER or DT_VCENTER
SetBkMode will likely trash EDX but you use it in DrawText.
Quote from: sinsi on May 02, 2024, 03:01:37 PMTried v3, clicking selected a cell but pressing keys did nothing, and the Load menu just blacked out the
is the file
'game.txt' in the same folder as the executable? It must be in the same folder as the executable. Also, the keys will not work if a game is not loaded first. I have been testing that program for quite some time, and have not had the issues that you are having.
Quote from: sinsi on May 02, 2024, 03:21:21 PMYou might be having trouble with EDX here
Now this I can fix... an oversight on my part
latest version attached in post #1
game.txt, no games.txt
It's the EDX that makes DrawText fail.
Quote from: sinsi on May 02, 2024, 03:32:42 PMgame.txt, no games.txt
was a typo..
QuoteIt's the EDX that makes DrawText fail.
latest version attached in post #1
No crashes now, but how do I replace what's in the selected cell? Related to that, for the game itself, there should be no indication that you've entered an incorrect number otherwise all you need to do is try every number until the red disappears :biggrin:
If you're trying to get the window to exactly fit the client area (your CenterWindow), I recently found AdjustWindowRectEx.
On my 4K monitor the game is tiny :badgrin:
@ sinsi:
It's not really a game per se, but my avatar creator - hence the thread title.
Yes it is tiny. 127x127... avatar sized (the sudoku board, anyway)
This project is still under development (and may still contain some unnoticed errors)
Thanks for your feedback. Do you have any other suggestions?
As far as replacing an invalid digit, don't make mistakes and you won't have to replace any invalid digits. :tongue: there is no undo function (will be, maybe in the near future)
You can always cheat and look at my avatar. :biggrin: until I change it, that is...
It's not perfect, but it works for what I need it to do. :smiley:
From now on, instead of keeping previous versions attached within their respective posts, I have decided to only have the latest version attached to post #1
When I make a post announcing some change to the program, that new version will be attached to post #1, and any prior versions removed.
I have been thinking....
Since I am developing this little toy concurrently with the continuing development of my sudoku GUI, why not do them within the same program... some of the code is already shared between them.
The avatar creation stuff would be done in a separate DC and not visible in the sudoku GUI. It seems that it should be 'doable'... I will run some tests later this evening (my time, it's noon here right now)...
The sudoku GUI btw, will not be posted until it is finished for those who might be interested. Please be patient. :azn:
Found an erroneous piece of code when trying to capture a portion of the client area starting at another position other than 0, 0 in the "DCbmptoFile" procedure.
It kept on capturing with results that I did not expect.
First, I had mislabeled the calculated height and width as 'xx' and 'yy'. Now changed those to ww and hh respectively.
xx and yy are now the origin x and y.
Next, I had forgotten to address the source DC's origin during BitBlt (was hard coded at 0, 0)
original code:
mov ecx, lprct
assume ecx:ptr RECT ;; set bitmap height & width from lprct (passed argument)
mov eax, [ecx].right
sub eax, [ecx].left
mov xx, eax
mov eax, [ecx].bottom
sub eax, [ecx].top
mov yy, eax
assume ecx:nothing
invoke CreateCompatibleBitmap, hDC, xx, yy
mov hBmp, eax
invoke SelectObject, tempDC, hBmp
mov hOld, eax
invoke BitBlt, tempDC, 0, 0, xx, yy, hDC, 0, 0, SRCCOPY
Which worked fine, as long as the origin was "0, 0" as in the lil_sudoku program.
Fixed the error, to have the origin anywhere within the client area:
mov ecx, lprct
assume ecx:ptr RECT ;; set bitmap height & width from lprct (passed argument)
mov edx, [ecx].left
mov xx, edx
mov eax, [ecx].right
sub eax, edx
mov ww, eax
mov edx, [ecx].top
mov yy, edx
mov eax, [ecx].bottom
sub eax, edx
mov hh, eax
assume ecx:nothing
invoke CreateCompatibleBitmap, hDC, ww, hh
mov hBmp, eax
invoke SelectObject, tempDC, hBmp
mov hOld, eax
invoke BitBlt, tempDC, 0, 0, ww, hh, hDC, xx, yy, SRCCOPY
:smiley:
The full procedure: :wink2:
;; converted to 32 bit by zedd151, from a 64 bit screen capture tool by Vortex.
;; modified by sudoku.
DCbmptoFile proc hDC:dword, lprct:dword, lpOut:dword ;; lpout is the output file name for the bitmap.
local hBmp:dword, hOld:dword, tempDC:dword, ww:dword, hh:dword, xx:dword, yy:dword
local hFile:dword, BmpSize:dword, SizeofDIB:dword, BWritten:dword, Bits:dword, pMem:dword
local bm:BITMAP, BmpFileHdr:BITMAPFILEHEADER, BmpInfoHdr:BITMAPINFOHEADER
push esi
push edi
push ebx
push edx
push ecx
xor eax, eax
lea edi, bm
mov ecx, sizeof BITMAP
rep stosb
xor eax, eax
lea edi, BmpFileHdr
mov ecx, sizeof BITMAPFILEHEADER
rep stosb
xor eax, eax
lea edi, BmpInfoHdr
mov ecx, sizeof BITMAPINFOHEADER
rep stosb
lea edi, bm
invoke CreateCompatibleDC, hDC
mov tempDC, eax
mov ecx, lprct
assume ecx:ptr RECT ;; set bitmap origin (xx, yy), height & width (hh, ww) from lprct (passed argument)
mov edx, [ecx].left
mov xx, edx
mov eax, [ecx].right
sub eax, edx
mov ww, eax
mov edx, [ecx].top
mov yy, edx
mov eax, [ecx].bottom
sub eax, edx
mov hh, eax
assume ecx:nothing
invoke CreateCompatibleBitmap, hDC, ww, hh
mov hBmp, eax
invoke SelectObject, tempDC, hBmp
mov hOld, eax
invoke BitBlt, tempDC, 0, 0, ww, hh, hDC, xx, yy, SRCCOPY
invoke GetObject, hBmp, sizeof(BITMAP), edi
mov BITMAP.bmBitsPixel[edi], 24
xor edx, edx
movzx eax, BITMAP.bmPlanes[edi]
mul BITMAP.bmBitsPixel[edi]
mov Bits, eax
lea ecx, BmpInfoHdr
mov BITMAPINFOHEADER.biSize[ecx], sizeof(BITMAPINFOHEADER)
mov eax, ww
mov BITMAPINFOHEADER.biWidth[ecx],eax
mov eax, hh
mov BITMAPINFOHEADER.biHeight[ecx],eax
mov ax,BITMAP.bmPlanes[edi]
mov BITMAPINFOHEADER.biPlanes[ecx],ax
mov ax,BITMAP.bmBitsPixel[edi]
mov BITMAPINFOHEADER.biBitCount[ecx],ax
mov BITMAPINFOHEADER.biCompression[ecx], BI_RGB
xor eax, eax
mov BITMAPINFOHEADER.biSizeImage[ecx], eax
mov BITMAPINFOHEADER.biXPelsPerMeter[ecx], eax
mov BITMAPINFOHEADER.biYPelsPerMeter[ecx], eax
mov BITMAPINFOHEADER.biClrUsed[ecx], eax
mov BITMAPINFOHEADER.biClrImportant[ecx], eax
xor edx, edx
mov eax, BITMAP.bmWidth[ecx]
mul Bits
add eax, 31
and eax, -32
shr eax, 3
mul BITMAP.bmHeight[ecx]
mov BmpSize, eax
invoke VirtualAlloc, 0, eax, MEM_COMMIT, PAGE_READWRITE
mov pMem, eax
invoke GetDIBits, tempDC, hBmp, 0, dword PTR BITMAP.bmHeight[edi], pMem, ADDR BmpInfoHdr, DIB_RGB_COLORS
xor eax,eax
invoke CreateFile, lpOut, GENERIC_WRITE, eax, eax, CREATE_ALWAYS, eax, eax
mov hFile, eax
mov eax, BmpSize
add eax, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
mov SizeofDIB, eax
lea edx, BmpFileHdr
mov BITMAPFILEHEADER.bfOffBits[edx], sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
mov eax, SizeofDIB
mov BITMAPFILEHEADER.bfSize[edx], eax
mov BITMAPFILEHEADER.bfReserved1[edx], 0
mov BITMAPFILEHEADER.bfReserved2[edx], 0
mov BITMAPFILEHEADER.bfType[edx], 'MB'
lea esi, BWritten
invoke WriteFile, hFile, ADDR BmpFileHdr, sizeof(BITMAPFILEHEADER), esi, 0
invoke WriteFile,hFile, ADDR BmpInfoHdr, sizeof(BITMAPINFOHEADER), esi, 0
invoke WriteFile, hFile, pMem, BmpSize, esi, 0
push eax
invoke CloseHandle, hFile
invoke VirtualFree, pMem, 0, MEM_RELEASE
invoke SelectObject, tempDC, hOld
invoke DeleteObject, hBmp
invoke DeleteDC, tempDC
pop eax ;; returns TRUE if file written, else returns FALSE
pop ecx
pop edx
pop ebx
pop edi
pop esi
ret
DCbmptoFile endp
where hDC is the DC of the captured client area. lprct is the pointer to rectange captured, lpout is pointer to the output file name for the bitmap. Also now taking better care to preserve the registers. :tongue:
As in my last couple of posts, I am working on 'big_sudoku' (will be renamed prior to going 'public').. It will incorporate a smaller (avatar sized 127x127) board within the GUI. The game will be played on the normal sized' sudoku board, and the smaller board will echo what is taking place in the main board (user can choose whether to show and use the smaller board or not). The screen captures on the smaller board will be automatic as soon as a value is entered (on the main board), if the small board is enabled. My current avatar was created with the help of this setup (yes, in its partially finished state). Much easier to work with the larger cells and of course font. :biggrin:
More details will follow in the coming days. Hopefully it will be completed (and bug free?) by the end of summer, time permitting.
Progess is slow, but I am making progress. I have devised a way to have the small (127x127) board and the Main sudoku board on the same DC, with the small (127x127) being invisible to the user - this simplifies matters a bit. (By not having to use multiple DC's) Now working on the core code now that the DC stuff is out of the way...
The avatar creator project is on hiatus until ...
... some time ...
... later.