Creating a DPaint clone in BMax

BlitzMax Forums/BlitzMax Programming/Creating a DPaint clone in BMax

QuickSilva(Posted 2007) [#1]
What would be the best way to go about making a pixel pushing paint program (say that ten times fast ;) in BMax? Is it a relatively simple task or would it be quite hard? I`m asking as I would like to try and make one but have never done anything other than games programming before. I`m not really sure as to how to go about it to tell the truth so any help would be great.

Jason.


Dreamora(Posted 2007) [#2]
It won't be fast.

Pixel operations in BM have to be done on pixmaps.
Those are either drawn to backbuffer (-> pixel per pixel copy) or have to be made an image which means texture generation and upload

In both cases, not fast enough to be "ten times faster" than anything done yet.

if you need it to be faster, check out shaders and do it as pixel shader for example.


grable(Posted 2007) [#3]
Or even easier, use DirectDraw surfaces, and keep it all 2D & still fast ;)


Brucey(Posted 2007) [#4]
say that ten times fast

I think he meant the alliteration :-p

A pixel-editor should be relatively easy to do in blitzmax. There are functions that can read/modify specific pixels in a pixmap, which is all you need.
The rest is up to you to implement how you wish :-)


Who was John Galt?(Posted 2007) [#5]
Even with the limitations of Blitz pixel pushing, speed will not be an issue. If by DPaint you mean deluxe paint on the Amiga (the last paint program I ever enjoyed using), 10x as fast will be easy.


ImaginaryHuman(Posted 2007) [#6]
Yeah, these days with the GPU-accelerated drawing and fast CPU's you shouldn't have much problem at all making a relatively fast graphics app.

I say go with OpenGL since DX is Windows only. I think if it were me I would write my own routines accessing pixmaps in main memory to do all the drawing, since that lets you have precice control over what is drawn and can make much larger bitmaps bigger than the screen. Then you can do things like flood fills where you'll need to READ the image. It's not so efficient to read the backbuffer and the backbuffer can only be the size of the screen resolution.

I would write the routines using pointers to access the individual pixels in the pixmap. Writing a paint program usually means writing quite a large number of small-ish specialized routines so it can be quite a bit of coding, but it's a good project. You need to ask yourself what you want it to be able to do in terms of sizes of bitmaps, resolution, color depth/palettes, etc... and also you've got to give consideration to how to do a GUI.


ImaginaryHuman(Posted 2007) [#7]
Yah, Amiga had lots of good paint software. Deluxe Paint, Brilliance, Personal Paint, TV Paint, Spectrapaint, etc etc


klepto2(Posted 2007) [#8]
Here is a small additon about fast pixmap manipulating and displaying. It is much faster for pixeloperations than the standard LockImage() or DrawPixmap stuff.

I think I have more time to explain it tomorrow.

SetGraphicsDriver(GLMax2DDriver())

Graphics 800,600,0,-1

Local Pix:TPixmap = CreatePixmap(512,512,PF_RGBA8888)
ClearPixels(Pix,$ffffffff)
Local Image:TImage = LoadImage(Pix)
Local Pix2:TPixmap 

'SetClsColor (255,255,255)
Local Mode:Int = 0
Local Radius:Int = 4
Local UpdateTime:Int = 0

Local fps:Int = 0
Local fpstime:Int = MilliSecs()
Local fps2:Int = 0
Local angle:Float = 0


While Not KeyHit(KEY_EScape)
	Cls
		SetColor 255,0,0
		DrawRect 0,0,516,516
		SetColor 255,255,255
		UpdateTime = MilliSecs()
		SetRotation Angle
		DrawImage Image,2,2
		UpdateTime = MilliSecs()-UpdateTime

		
		If KeyHit(Key_Space) Then 
			If Mode = 2 Then 
				Mode = 0 
			Else
				Mode = 1 - Mode
			EndIf
			Angle = 0
			SetHandle 0,0

		EndIf
		
		If KeyHit(KEY_Enter) Then 
			angle = 0
			Mode = 2
			SetHandle 256,256
		EndIf
		If KeyHit(Key_Up) Then Radius:+1
		If KeyHit(Key_Down) Then Radius:-1
		If Radius < 1 Then Radius = 1
		Local MX:Int = MouseX()
		Local MY:Int = MouseY()
		
		Local XX = Min(Max(2,MX),514)
		Local YY = Min(Max(2,MY),514)


		If Mode <> 2 Then 
		If MouseDown(1) = True Then
			If MX > 2 And MX < 512
				If MY > 2 And MY < 512
				If Mode = 1 Then
					Pix = LockImage(Image)
				 EndIf
					For Local Xi:Int = 0 To radius
						For Local yi:Int = 0 To radius
						 
							Local X = Min(Max(2,MX+xi),512)
							Local Y = Min(Max(2,MY+yi),512)

							WritePixel Pix,X-2,Y-2,$ff000000
							
						Next
					Next
					
					If Mode = 0 Then
						UploadPixToImg(Image,Pix,XX-2,YY-2,radius+2,radius+2)
					EndIf
					
				EndIf
			EndIf
		EndIf
			Else
			Angle:+0.2	
		EndIf
		
		SetRotation 0.0
		
		DrawText "Mode       : " + Mode,20,515
		DrawText "Radius     : " + Radius,20,535
		DrawText "UpdateTime : " + UpdateTime,20,555
		DrawText "FPS        : " + FPS,532,20
		DrawText "Space       -> Change Mode (0 = Fast,1 = LockImage)",532,40
		DrawText "Up and Down -> Change Radius",532,60
		DrawText "Color      :  $" + Hex(ReadPixel(Pix,Min(Max(0,MouseX()-2),511),Min(Max(0,MouseY()-2),511))),20,575
		
		fps2:+1
		
		
		If MilliSecs()-fpstime >= 1000 Then
			fps = fps2
			fpstime = MilliSecs()
			fps2 = 0
		EndIf
		
		If KeyHit(KEY_F1) Then SavePixmapPNG(Pix,"test.png")

	Flip 0
Wend




Function UploadPixtoImg(tex:TImage,Pixmap:TPixmap,x:Int = -1,y:Int=-1,w:Int=-1,h:Int=-1)
	Local ImgF:TGLImageFrame = TGLImageframe(tex.frame(0))
	Local mip_level:Int = 0

		If ImgF <> Null Then
			glBindtexture GL_TEXTURE_2D,ImgF.name
			glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
			If X <> -1 And y <> -1 And w <> -1 And h <> -1 Then
				glTexSubImage2D GL_TEXTURE_2D,mip_level,X,y,W,H,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixelptr(X,Y)
				
			Else
				glTexSubImage2D GL_TEXTURE_2D,mip_level,0,0,pixmap.width,pixmap.height,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
			EndIf
			glPixelStorei GL_UNPACK_ROW_LENGTH,0
			glBindtexture GL_TEXTURE_2D,0
		EndIf
		
	DrawText " ",-20,-20
End Function



sebas76(Posted 2007) [#9]
Hi all,

Tvpaint has been ported to PC.
You can try Aura from Newtek or Tvpaint or Mirage.
These 3 soft are Tvpaint version.
They are the best paint software for amiga lovers...


rno(Posted 2016) [#10]
maybe interesting:

With the permission of Electronic Arts, Inc. the Computer History Museum makes available, for non-commercial use, the source code to the 1986 version I of DeluxePaint. There are 89 files of C language source:

http://www.computerhistory.org/atchm/electronic-arts-deluxepaint-early-source-code/


coffeedotbean(Posted 2016) [#11]
many a good hour I spent making animations in DPaint on my Amiga, mostly just planes spinning in and out due to that automated feature it had to scale and move.


dw817(Posted 2016) [#12]
Nice code, Klepto2 !

I think he is not necessarily saying that he wants the code to go 10x fast, but to say the PHRASE, "pixel pushing paint program" 10x fast, as it is definitely a tongue-twister. And no, I can't do that. Not without another cup of coffee. :)

Here is my code on the issue, Jason:




To doodle, put the mouse anywhere and hold down the mouse button. To erase, hold down the BACKSPACE key. To exit press the ESCAPE key. You can definitely see this is a pixel pusher program.


Kryzon(Posted 2016) [#13]
This is an eight-year-old thread. The author has most likely long moved on (I'm saying this because you mentioned his name as if referring to him directly).
He won't read your post.

I've been meaning to tell you; if you want to help grow the codebase of something in need of contributors like you, the MonkeyX-2 project is ideal:
http://www.monkey-x.com/Community/topics.php?forum=230

It's the latest language by the maker of BMax, but it's obscure to the general public and needs code examples.
It's free to make an account there and start posting. If you want to cause a positive impact, that is the place.


dw817(Posted 2016) [#14]
As I've mentioned before, Kryzon, my code is for everyone to see and learn from. He MAY read it. There are no absolutes in life. Don't be so negative. :)

RNO is certainly optimistic and I applaud that.

Now I tried a little Monkey-X a few weeks back. While the EXE runtime seems fine, it staggers considerably in the Firefox browser. I would like to know what is causing that first before I dedicate any serious time to it.

Now I HAVE written FLASH in the past for Online usage and it certainly runs smoother than Monkey-X.

As you know, there is considerable support for BlitzBASIC, but I chose BlitzMAX primarily for the flip() command which ensures smooth graphics and low CPU usage always.

Those to me are key.


Endive(Posted 2016) [#15]
One point about paint programs that may not seem obvious to game programmers is the fact that you don't need to do full-screen updates, or even have a regular frame tick on the canvas area-- instead your ticks only happen when the user actually does something.


dw817(Posted 2016) [#16]
Endive, the problem with this is, suppose you want to have background images run while you are navigating menus ?

If you don't clear the screen every machine cycle and redraw everything, you will have graphic elements lock up while you are involved in some other loop.

That S3 engine bit I uploaded earlier, you notice that absolutely nothing slows it down once it's going. You can navigate menus or anything else and all elements continue to run in background at the exact speed and timing they are supposed to.

The secret ? Clear the screen to BLACK and redraw absolutely every single element that is needed - every single cycle.

Now your method =WILL= work if you use a series of overlaying grids only of image data with no transparency effects. And that will be considerably faster too.

But Truetype Fonts, most of them, are not monospace, so that method is out for them. Also if you have some graphic elements bigger or smaller than the grids you use, or you want to have some elements appear through partially transparent frames.

So far the CPU is at 18% with my current 2016 engine. My envelope is 25%, and this a 64-bit quad core computer.

At that point I need to start writing faster and more intelligent code, however and whatever it takes to do so.


dw817(Posted 2016) [#17]
I also did want to add, I have written MANY functions for Monkey-X. I tried a game this morning found on NewGrounds written with it, and the graphics are smooth with little CPU usage - so - I will give it another go.

What I especially need right now is the code to draw pixels, to read them, and to read raw keystrokes, and to read and write data directly from the Internet (as runtimes are stored there). Also whatever command is used to prematurely end a runtime in the middle of the code so I can do some debugging.

With those things I can start to write demos, games, and utilities in it.

Here are the functions I've written thus far that are NOT found in Monkey-X's command set.

val(), asc(), mid$(), len(), fnc$(), fno$(), fnz$(), upper$(), lower$(), firstcap$(), trim$(), instr().

I'm current working on writing chr$(), bound(), wrap(), and rinstr() ATM, which are also not part of Monkey-X's command set.


Brucey(Posted 2016) [#18]
There's a whole other forum devoted to chatting about Monkey - http://www.monkey-x.com/Community/_index_.php

This is the BlitzMax forum.


dw817(Posted 2016) [#19]
Yeah, I know Brucey, but Kryzon brought it up so I thought I would reply proper. In any case, I can check there and see what is happening.

I will wander between both and certainly produce more BlitzMAX code to answer questions posed. So - you won't get rid of me that easily. :)


Kryzon(Posted 2016) [#20]
That's a great idea, adding BASIC commands to the Monkey API. You need to share those in some way, so I suggest setting up a GitHub account.

What I especially need right now is the code to draw pixels, to read them

The graphics modules of Monkey, BlitzMax and other modern engines use GPU textures, instead of memory buffers as it was done with older technologies.
If you want pixel manipulation, you need to learn how texturing works in OpenGL.

The most likely end result will be that you keep a local copy of the texture as a memory buffer, make changes to it and then upload it to the GPU (by means of special OpenGL functions).
The GPU is not designed to get things back and forth efficiently between system RAM and video RAM.
It's meant for you to do something once, upload it to the GPU memory (so the asset lies in that fast internal memory) and draw it from there.


dw817(Posted 2016) [#21]
What is GitHub ? Certainly I can just post the source code in the "http://www.monkey-x.com/Community/_index_.php"

Yes, my main engine (BlitzMAX) is using a 'texture' to create the screen. I'm - not very comfortable with it, but it does work now the way I want it to.

I honestly don't know what DarkBASIC is doing or if they are even in business anymore. But I do know that they focused on full-screen graphics for the programmer, ultimately. And that was a plus in my book at the time.

I never have been comfortable with programming languages that force texturing down your throat - or object orienting.

I'm old-school, that should be apparent, and I like my graphic screens to be easily accessible, fast, black, and full size, and my programs to plot individual pixels as-fast-as-humanly-possible where I can control the speed and CPU usage additionally.


Endive(Posted 2016) [#22]
Endive, the problem with this is, suppose you want to have background images run while you are navigating menus ?

If you don't clear the screen every machine cycle and redraw everything, you will have graphic elements lock up while you are involved in some other loop.

Dirtyrects. A dirtyrects algorithm keeps track of the areas of the screen that need to be redrawn (divide it up into 32x32 tiles, say) and then redraws only those.

In a paint program, you don't need to redraw your whole screen every tick. Only the areas that have actually changed. If you are working in lower resolution (eg for a pixel art program) this may not matter because of the lower resolution but even for 4x4 pixels on a 1600x1000 grid you will start seeing slowdown if you are trying to update every tick.

Also since your paint program is not doing anything animated there should be no reason to update every tick.

Basically all windowing systems used dirtyrect repaints at least until fairly recently with compositing happening on the GPU.


dw817(Posted 2016) [#23]
Redraws only areas of the screen that need to be redrawn, Endive ? Hmm ... I have yet to see easy code on how to draw directly to a TIMAGE or TPIXMAP, and by that I mean not one pixel at a time but using drawline(), drawrect(), and any other normal graphic commands - as if it were the graphics screen.

As I mentioned earlier, in GFA, it's:
newdc=memdc(_dc(1))
bmpdc=createbmp(1024,768)
setbmp newdc,bmpdc
setdc newdc
Where _dc(1) is the standard display. Using this method above, you can create a virtual 'screen' and save it to pointer newdc. Anytime you want to plot invisibly, just have your dc set to newdc

to copy this hidden screen to the normal screen it's:
bitblt newdc,0,0,1024,768,_dc(1),0,0,SRCCOPY
Pretty straight-forward, and not too many commands to invoke. This is what I am looking for in BlitzMAX.

I think there is a command like GFA's SETDC where you can change the Display Channel to write directly to a tpixmap or timage, I'm just not sure how to do it.

With easy code for that, Dirtyrects() might be something interesting I could make use of - and not until.


Endive(Posted 2016) [#24]
Redraws only areas of the screen that need to be redrawn, Endive ? Hmm ... I have yet to see easy code on how to draw directly to a TIMAGE or TPIXMAP, and by that I mean not one pixel at a time but using drawline(), drawrect(), and any other normal graphic commands - as if it were the graphics screen.

It may or may not exist but it would take you 20 minutes to write drawline and drawrect up from writepixel. See the bresenham line drawing routine I posted in my rasterizer (pretty sure that's from here originally).

You could also do it with grabimage of modified areas into tiles, then when you do redraws, just redraw the tiles. There isn't a native Blitz command to draw directly to TImages but you certainly can draw to the screen, then grabimage from that into a TImage.

Grabimage is sort of slow though so you aren't going to be able to do a whole lot of those.

You could also roll your own RGB array and then do pixel draws out of that, but there you're back to writing your own draw primitives.

If you are serious about writing a paint program you are probably going to want to do the above anyway. It could have a CLUT table, palettes, etc.


dw817(Posted 2016) [#25]
No, I've already written a paint program, if you want to call it that. It's TileMaster, a reincarnation of the original from Commodore Amiga. It's quite powerful, works directly with tiles of any size up or down and essentially uses every single key on the keyboard for editing, archiving, assembling, and manipulation. Ahh - I think it's just for me to use. :)

I wrote it in BlitzMAX about 5-years ago. It works great, but it would've been a lot easier to build if I could just draw directly to a tpixmap or timage as a virtual screen.


Endive(Posted 2016) [#26]
I wrote it in BlitzMAX about 5-years ago. It works great, but it would've been a lot easier to build if I could just draw directly to a tpixmap or timage as a virtual screen.

Once again you would need some sort of intermediary object wrapper.


Endive(Posted 2016) [#27]
I'm working on something involving the same issues so here is a pixmap drawline and plottopixmap. You should be able to write drawrect in two minutes given drawlinetopixmap.

Notice that the drawline routine gets its colors from setcolor and setalpha and performs the hex conversion itself.

Function DrawLinetoPixmap(inpixmap:TPixmap,X1:Int,Y1:Int,X2:Int,Y2:Int)
	'Draws a line of individual pixels from X1,Y1 to X2,Y2 at any angle
	Local r%,g%,b%,alpha#
	GetColor(r,g,b) ' getcolor uses var so we are setting r,g,b to whatever setcolor is using
	a=GetAlpha()
	Local col:Int = (r | g Shl 8 | b Shl 16 | a Shl 24 )  '  << NOTE THIS, converts int rgb to hex
 	Local Steep:Int=Abs(Y2-Y1) > Abs(X2-X1)			'Boolean
	If Steep
		Local Temp:Int=X1; X1=Y1; Y1=Temp		'Swap X1,Y1
		Temp=X2; X2=Y2; Y2=Temp		'Swap X2,Y2
	EndIf
	Local DeltaX:Int=Abs(X2-X1)		'X Difference
	Local DeltaY:Int=Abs(Y2-Y1)		'Y Difference
	Local Error:Int=0		'Overflow counter
	Local DeltaError:Int=DeltaY		'Counter adder
	Local X:Int=X1		'Start at X1,Y1
	Local Y:Int=Y1		
	Local XStep:Int
	Local YStep:Int
	If X1<X2 Then XStep=1 Else XStep=-1	'Direction
	If Y1<Y2 Then YStep=1 Else YStep=-1	'Direction
	If Steep Then Plottopixmap(inpixmap,Y,X,col) Else Plottopixmap(inpixmap,X,Y,col)		'Draw
	While X<>X2
		X:+XStep		'Move in X
		Error:+DeltaError		'Add to counter
		If (Error Shl 1)>DeltaX		'Would it overflow?
			Y:+YStep		'Move in Y
			Error=Error-DeltaX		'Overflow/wrap the counter
		EndIf
		If Steep Then Plottopixmap(inpixmap,Y,X,col) Else Plottopixmap(inpixmap,X,Y,col)		'Draw
	Wend
End Function

Function plottopixmap(p:TPixmap,x#,y#,col%)
	p.WritePixel(x,y,col)
End Function



dw817(Posted 2016) [#28]
This is nice code you've written, Endive - and while I can certainly go this route, to write all my own graphics routines a pixel at a time. I still would prefer to have a way of "poking" BlitzMAX so I can change the regular display to write directly to an open pixmap or timage, especially since my way of handling screen updates are done with commands like this:
              If i=0
                setcolr 4,4,4
                SetBlend alphablend
                SetAlpha 1
                DrawImage img_frame[c,0],kk*16,j*16
              ElseIf i=1
                wht              
                SetBlend lightblend
                SetAlpha .5
                DrawImage img_frame[c,1],kk*16,j*16
              ElseIf i=2
                blk
                SetBlend alphablend
                SetAlpha .5
                DrawImage img_frame[c,2],kk*16,j*16
              ElseIf i=3
                SetColor rr,gg,bb
                SetBlend alphablend
                SetAlpha 1
                DrawImage img_frame[c,3],kk*16,j*16
                wht
              EndIf
I think you mentioned it, why rewrite what already works - unless there is a way of transferring one pixmap piece or whole to another pixmap's piece or whole WITHOUT using For/Next, no, where it is an existing command in BlitzMAX.
CopyPixmapPiece sourcepix,pixsourceh,pixsourcev,pixsourcex,pixsourcey,destpix,pixdesth,pixdestv,pixdestx,pixdesty,type
Where Type could be any of your usual copy methods of MASKEDIMAGE, FILTEREDIMAGE, MIPMAPPEDIMAGE, and DYNAMICIMAGE.


Endive(Posted 2016) [#29]
That's the point, to my knowledge it doesn't exist. The TImage/TPixmap interface has always been a little bit rough.


dw817(Posted 2016) [#30]
Actually, it does, the part of being able to write normal graphics directly to a pixmap, Casaber did it ... retrieving link:

http://www.blitzbasic.com/Community/post.php?topic=105546&post=1287365

Pretty neat stuff, but the code all around it is a bit much. Should be a way of trimming it down.


Derron(Posted 2016) [#31]
That code is OGL only ... dig the forums, there is also code for DX - you "just" need to make both conform and "blitzmax-driver"-like, so the correct thing is used automatically (or use some wrapper).

Without ... your r2t code just works on certain platforms / setups - some users of my game TVTower reported problems with OGL, they would then not be able to run your app.


@refresh each frame
A real "GUI"-paint-program wont need to do this, as it gets informed whether its content needs a RePaint (or more detailed: the corresponding GUI widget - most likely the canvas - gets the event for a repaint/refresh).

The whole screen content is already managed by the OS, so they take care of what was hidden by a cursor, another application ...


Dirty Rects: code should be available in the forums, but it is not running flawless on every computer as the content might get garbled / destroyed by the GPU). I once was able to use some kind of dirty rects on my old SIS 631 GPU (2004 or so ?) but it did not work on the Radon 9600 Pro anymore :-)


So what does this mean for your GUI program: you get the repaint / refresh event and handle it: you update your canvas-content. If you now use some kind of "render to texture" you are easily able to offload some processing to the gpu.

Another approach is to use Max2D ...
SetGraphics CanvasGraphics(self.canvas)
SetBlend AlphaBlend
SetViewport( 0,0,self.showDimension.getX(),self.showDimension.getY() )
SetClsColor 255,255,255
Cls
[...]


So you "blitzmax-like-draw" on request of the OS instead of intervals (refresh rate, timers...).

Just think of it to behave similar to "gui buttons". Methods:

a) check in each loop if button.clicked > 0.
b) react on "onButtonClicked" (with your event handler attached)


For your canvas this is
a) render it again on each "loop"
b) wait for the OS to say it is needing a new "canvas content"

There might be the need to update the canvas regardless of "got dirty"-events: if you are eg. showing drying colors (you paint with water colors and it smears, tears down ...). This is the exception, but this could then handled with timers, and skipped redraws if there was no change on the canvas (remember: drawing something to the screen is "cpu expensive").


bye
Ron


Endive(Posted 2016) [#32]
Dirty Rects: code should be available in the forums, but it is not running flawless on every computer as the content might get garbled / destroyed by the GPU). I once was able to use some kind of dirty rects on my old SIS 631 GPU (2004 or so ?) but it did not work on the Radon 9600 Pro anymore :-)


I would just ghetto it up using a screenful of 32x32 tiles and wrapped draw calls that notify a tile when it's been written to.


dw817(Posted 2016) [#33]
Hi Derron, I'm getting an error on your code: "Identifier "CanvasGraphics" not found.

Endive, I can write a dirtyrects routine myself I imagine and it would be flawless (or pretty close to it). :)

But I'm missing something, doesn't BlitzMAX already handle this sort of thing ? Drawing to the screen all your changes when you use flip() ?

Also, this gives problems I found, the fault lies in "SetGraphicsDriver(GLMax2DDriver())"

SetGraphicsDriver(GLMax2DDriver())
graphics 640,480
repeat
  cls
  drawoval 320-16,240-16,32,32
  flip
  flip
until keydown(27)


without the SetGraphicsDriver() command, it works fine. Is there a way to have this not flicker but still use the SetGraphicsDriver() command ? I normally use flip and flip when seeing final code to see if in those it runs at "normal" speed and save using only one flip for faster debugging.


Derron(Posted 2016) [#34]
My code was just a snippet of my spritepacker gui...something using MaxGUI.

@dirtyrectS
The problem is not the "what is clean..and what is dirty"-logic but the backbuffer. You think it is kept valid but the system might throw it away..leaving valid pixels...and overwritten ones. So you do not have a warranty of seeing the same content after the next flip.


Bye
Ron


BlitzMan(Posted 2016) [#35]
Here is a paint program in blitz not bmax,with source.May help may not,never used it.

written by Angus Arthur 2001.

before ppl complain its in code archive,or gallery ppl give away there code in the gallery.

http://www.filedropper.com/bpaint742002


dw817(Posted 2016) [#36]
Blitzman, WOW, reading the variables in the beginning. That's a BUNCH !

I know when I was working on early S3, it was a nightmare to code all that in. So - I didn't !

Instead I wrote a program in BM that was a bit like a database, I told it what BlitzMAX code to generate to initialize and load all the variables for my engine correctly, and it would generate a text file I later called, "MERGE." because you can merge external files in your BlitzMAX code. As I used it:
' / / / / / / / / / /
Include "merge.bmx"
' / / / / / / / / / /


Doing this kept my main sourcecode clean.

Any chance of getting the EXE of Angus's paint program so I can see it proper ?

Derron, using the 'virtual screen' method, that might make it a lot easier to maintain and keep a 100% accurate dirtyrects.


BlitzMan(Posted 2016) [#37]
Download the free Blitz3D,and run the code in that. dw817


dw817(Posted 2016) [#38]
BlitzMan, here is the page to download:



If this is not the right area, could you post direct URL, please ?


BlitzMan(Posted 2016) [#39]
I could post a copy of the Blitz3D program,being open source,and such but im not sure i am aloud to.If not try Ploppy`s Hybrid version.


Brucey(Posted 2016) [#40]
Go to your Account page, then click on "Register Product". Follow the instructions...

Once you've registered, go to the "Product Updates" page and you should see it listed in the downloads next to the BlitzMax ones.


dw817(Posted 2016) [#41]
That's okay, BlitzMAX. PM me about the Hybrid version tho, curious.

Got B3D up and going, thanks Brucey. Tried the paint program. Err ... ?? Yeah, mine's a bit better than that, not to toot my own horn.

I downloaded IDEAL which is a marvel of an IDE, but I can't get it to compile anything. Did they ever make an IDE with as much if not more ability for BlitzMAX ?