Author Topic: SpriteEditor  (Read 4365 times)

johnno56

  • Guest
SpriteEditor
« on: November 15, 2014 »
No... Not another one...

This is my first attempt using N6. There isn't much to show at the moment. I have basically created a variable grid. From 16x16 to 64x64. The next phase is to work out how to transfer colour from the sampler to the grid. I will also attempt an update area to display the sprite in real time. The next phase, hopefully, will include some basic file control buttons. I don't have a clue on where to start, when is comes to basic drawing buttons. The coding, not the actual buttons...

I am flying by the seat of my pants with this one. Searching through the N6 example for clues as to what to do next. My code is sloppy at best but it seems to be working.

I would appreciate ANY feedback. Good or bad. Maybe, when it is finished, someone else can "polish it up" and perhaps integrate it into the Raycaster or Tile Map Editor?

John

  • Sr. Member
  • ****
  • Posts: 362
    • View Profile
Re: SpriteEditor
« Reply #1 on: November 15, 2014 »
Reminds me of the sprite/bob editor in Amiga AMOS :) I think this can be very useful, because GIMP isnt' that fun to work with when it comes to pixel art.

I wrote some simple button routines for my jigsaw game. You can have a look at the below code and use it if you want to. Call 'NewButton(label$, x, y)' to create a new button at some position. There are some helper functions to put buttons next to eachother, but you can stick to simple x and y coordinates.

Code: [Select]
rem Button stuff.

visible:
rem Button data.
buttons?[]
buttonCol[][] = [[0xa0a0a0, 0xffffff, 0x0, 0x0], [0xa0a0a0, 0xffffff, 0x0, 0xffffff], [0x808080, 0x0, 0xffffff, 0x0]]
buttonCount
buttonFont

hidden:

set redraw off

easyButton = NewButton("Load easy puzzle", 4, 400)
hardButton = NewButton("Load hard puzzle", RightOfButton(easyButton) + 4, ButtonY(easyButton))
scrambleButton = NewButton("Scramble", RightOfButton(hardButton) + 4, ButtonY(easyButton))
loadButton = NewButton("Load state", ButtonX(easyButton), BelowButton(easyButton) + 4)
saveButton = NewButton("Save state", RightOfButton(loadButton) + 4, ButtonY(loadButton))
quitButton = NewButton("Quit game", RightOfButton(saveButton) + 4, ButtonY(saveButton))

dummy$
do
btn = zone()

if btn = easyButton
dummy = "The easy button"
elseif btn = hardButton
dummy = "The hard button"
elseif btn = scrambleButton
dummy = "The scramble thingy button"
elseif btn = loadButton
dummy = "The load something button"
elseif btn = saveButton
dummy = "The save everything button"
elseif btn = quitButton
end
endif

set color 64, 64, 64
cls

proc DrawButtons

set color 255, 255, 255
set caret 16, 16
wln "Last button pressed: " + dummy

redraw
wait 16
until keydown(27, true)

rem Remove all buttons.
procedure ClearButtons()
for i = 0 to buttonCount - 1
free zone i + 1
next
buttonCount = 0
buttons?[]
endproc

rem Set button font.
procedure SetButtonFont(index)
buttonFont = index
endproc

rem Create new button.
function NewButton(label$, x, y)
if buttonCount = 0
buttons?[10]
elseif buttonCount = sizeof(buttons, 0)
newButtons?[buttonCount + 10]
for i = 0 to buttonCount - 1
newButtons[i] = buttons[i]
next
buttons?[] = newButtons
endif
w = fwidth(buttonFont, label) + 8
h = fheight(buttonFont) + 6
buttons[buttonCount].label$ = label
buttons[buttonCount].x = x
buttons[buttonCount].y = y
buttons[buttonCount].w = w
buttons[buttonCount].h = h
create zone buttonCount + 1, buttons[buttonCount].x, buttons[buttonCount].y, w, h
buttonCount = buttonCount + 1
return buttonCount
endproc

rem Get button x.
function ButtonX(btn)
return buttons[btn - 1].x
endfunc

rem Get button y.
function ButtonY(btn)
return buttons[btn - 1].y
endfunc

rem Get x right of button.
function RightOfButton(btn)
return buttons[btn - 1].x + buttons[btn - 1].w
endfunc

rem Get y below button.
function BelowButton(btn)
return buttons[btn - 1].y + buttons[btn - 1].h
endfunc

rem Draw buttons.
procedure DrawButtons()
set font buttonFont
for i = 0 to buttonCount - 1
bstate = zone(i + 1)
set colori buttonCol[bstate][0]
draw rect buttons[i].x, buttons[i].y, buttons[i].w, buttons[i].h, true
set colori buttonCol[bstate][2]
draw rect buttons[i].x, buttons[i].y, buttons[i].w, buttons[i].h, false
set colori buttonCol[bstate][1]
draw line buttons[i].x, buttons[i].y, buttons[i].x + buttons[i].w - 1, buttons[i].y
draw line buttons[i].x, buttons[i].y, buttons[i].x, buttons[i].y + buttons[i].h - 1
set caret buttons[i].x + 4, buttons[i].y + 3
set colori buttonCol[bstate][3]
write buttons[i].label$
next
endproc
« Last Edit: November 15, 2014 by John »

Rick3137

  • Sr. Member
  • ****
  • Posts: 347
  • May the Force be with You
    • View Profile
    • Rick's Programs
Re: SpriteEditor
« Reply #2 on: November 15, 2014 »
 This is a really cool idea for another NaaLaa tool. I have been using the little Microsoft paint program to do my pixel drawing. This is very similar.
 I like the idea of a tool made with NaaLaa that we can add features to, whenever we think of a new feature that can make drawing smoother.

Marcus

  • Administrator
  • Hero Member
  • *****
  • Posts: 549
    • View Profile
Re: SpriteEditor
« Reply #3 on: November 15, 2014 »
Automatic layout of sprites in image grids ... Yes, this could be very useful! No preassure Johnno, right :)
.\\\opz

kcfb

  • Jr. Member
  • **
  • Posts: 80
    • View Profile
Re: SpriteEditor
« Reply #4 on: November 15, 2014 »
Echo the thoughts above.....I struggle with art, even with the simplest tools, so the idea of having a tool written in NaaLaa and incorporating ideas from the community is really good.....Best wishes for the project....

johnno56

  • Guest
Re: SpriteEditor
« Reply #5 on: November 16, 2014 »
John:

Thanks for the "button" code sample. I am please that 'you' call it 'simple', for me it's a bit of a minefield, question marks and dots in the variables. You realize I'm gunna be asking about those... ;) Awww. A bit harsh on Gimp? I think it's cool because I have been using it for years. (I restore photos as a pastime...). Again. Thanks for the code.

Rick:

I suppose it would be really cool, assuming I can finally get it finished, and working. But, I agree, the more tools that are Naalaa based has to be a good deal. I tried making this, using a basic-like language that will not be named because it may be considered 'spamming', but couldn't finish it because of not being able to list existing files to import. Anyway. That's a 'bit down the road' from where I am at the moment.

Marcus:

You are 'not' applying pressure. I am doing more of that on my own as it is.... ;)

Rick:

Thanks for that. I am trying to keep it simple or very basic, so that people with a natural aversion to Paint, Gimp or Photoshop, can produce an image that 'will do the trick' with as little of fuss as possible. Speaking of changes: For those of us that are keen on extreme 'retro' (8 bit graphics), I will include an 8 bit grid option on the next release. I tried a 128x128, but found the grid was soooo small, that it made it hard to see each cell.

kcfb:

Art has not been a problem for me, but I realize that, it may be for others. Once the 'learning curve' has been done on the larger graphics editors, they can be quite useful and almost fun to use. As I mentioned to Rick, I am deliberately trying to 'keep it simple', for just that reason.

To all:

Many thanks for the comments (and code) and thoughts. I am probably going to pester you all for some more much valued assistance. I feel a little (hmm maybe a lot) out of my depth. If this application looks like it will work, I will move it from 'snippets' to 'projects'. Again. Thank you all for your help. Much appreciated.

J

johnno56

  • Guest
Re: SpriteEditor
« Reply #6 on: November 17, 2014 »
I am at a stage in development where I need to sample a colour and with that selected colour to draw on the grid. Normally I would either draw a filled rectangle or just flood fill the grid cell.

Ok. Here is my first problem. I noticed the lack of a floodfill command, and yes, I did see the floodfill routine in the N6 examples that Marcus produced. His fill is a recursive fill. Which, under normal circumstances, works like a charm. My situation is that, I run N6 on my Linux box via Wine, and a recursive fill plays havoc with memory.

I do not need the fill to occupy an irregular shape. All I am filling are squares. Therefore, I have chosen to use a boundary fill routine. It's a little slower than a recursive, but the areas I intend to fill are much smaller.

I have tested the routine, using another basic-like application which will remain nameless to avoid spamming, and it works fine. I am having difficulty with the "pixeli(x,y)" command. Correct me if I am wrong. pixeli() will return the colour at x,y as a single integer value (c) and "set colouri c" combined with "set pixel x,y" will draw a dot of the same colour that pixeli detected?

I am not familiar with the policies of this forum, in regards to, posting code from another language. It would be much easier for me to "show" you the listings instead of trying to describe it. If I cannot publicly post it, perhaps I can send it in a private message. If none of these options are acceptable, can someone at least let me know if my understanding of the above commands are accurate, and then I can attempt a 'work-a-round'. I hope I am making sense?

Many thanks

J

johnno56

  • Guest
Re: SpriteEditor
« Reply #7 on: November 17, 2014 »
Can someone please explain why this does not work? I do not know how many times I have gone over this.

What I hope to do is: Display colour samples. Create a zone to limit the mouse choice. Click the left mouse button and as long as the mouse is not pointing to the actual grid, detect the colour and reproduce it in the blank square. Simple? I am going nuts trying to figure it out. I am almost certain that it is the pixeli() command, but I cannot be sure. What am I doing wrong?

Code: [Select]
set window 0,0,640,480
set color 0,0,0
set redraw off
cls

load image 1, "colourpatch.png"

create zone 1,0,0,288,200

constant:

gridcol 0x808080

visible:

do

set color 255, 255, 255
draw image 1, 0,0
set color 128,128,128
draw rect 300,250,25,25,false

if mousebutton(0) and zone(1) and pixeli(mousex(),mousey()) <> gridcol then
current = pixeli(mousex(),mousey())
set colori current
draw rect 301, 251, 23, 23, true
endif
redraw
wait 10

until keydown(27) or not running()

Peter

  • Guest
Re: SpriteEditor
« Reply #8 on: November 17, 2014 »
Hi Johnno,

Do you mean  such a thing like this ?
Code: [Select]
set window 0,0,640,480
set color 0,0,0
set redraw off
cls

load image 1, "colourpatch.png"

create zone 1,0,0,288,200

constant:

gridcol 0x808080

visible:
r5;g5;b5

do
set color 0,0,0,255
cls
set color 255, 255, 255,255
draw image 1, 0,0
set color 128,128,128
draw rect 300,250,25,25,false
 
set color 255,255,255,255
set caret 10,400
wln str(mousex())
set caret 10,410
wln str(mousey())
set caret 10,420
wln str(current)

if mousebutton(0) and mousex() >=0 and mousex() <=288 and mousey() >=0 and mousey() <=201 then
  current = pixeli(mousex(),mousey())
r5 = getR(current)
   g5 = getG(current)
   b5 = getB(current)

   set color r5,g5,b5
draw rect 301, 251, 23, 23, 1
endif
redraw
wait 10

until keydown(27) or not running()

function getB(n_c)
    return n_c AND 255
endfunc   

function getG(n_c)
    return (n_c SHR 8) AND 255
endfunc   

function getR(n_c)
    return (n_c SHR 16) AND 255
endfunc

Peter

  • Guest
Re: SpriteEditor
« Reply #9 on: November 17, 2014 »
I think that COLORI works in the wrong direction!  ;D

John, what about STATIC VARIABLES ?

If 'current' would be a static variable, it would hold the value!
« Last Edit: November 17, 2014 by Peter »

John

  • Sr. Member
  • ****
  • Posts: 362
    • View Profile
Re: SpriteEditor
« Reply #10 on: November 17, 2014 »
The alpha channel of the primary surface is sort of undefined ... sometimes. Just mask it out everytime you call pixeli.

Code: [Select]
c = pixeli(x, y) AND 0xffffff

I will check it out completely when I'm home.

johnno56

  • Guest
Re: SpriteEditor
« Reply #11 on: November 17, 2014 »
Peter,

That's almost it. The only problem is that the selected colour in the square is supposed to remain until the next colour is selected. The condition implies that the selected colour will appear in the square as long as the mouse button is pressed otherwise without a selected colour, the default colour would be zero, or black. Well, that's my understanding of the logic, but I have be known to be wrong...

Many thanks. That's way better than I could have done...

J

John

  • Sr. Member
  • ****
  • Posts: 362
    • View Profile
Re: SpriteEditor
« Reply #12 on: November 17, 2014 »
I added a function in the code below, getrgb, that works the way that you usually (as in "99% of the time" ...) want pixeli to work. I suggest you simply use it instead. All it does is the thing I did in my previous post, mask out the unreliable alpha channel.

Sorry about the trouble. It's really stupid, because working with the alpha channel on colors in this integer format is almots impossible anyway since naalaa doesn't support unsigned integers (required for actually dealing with 32 bit colors).
 

Code: [Select]
set window 0,0,640,480
set color 0,0,0
set redraw off
cls

load image 1, "colourpatch.png"

create zone 1,0,0,288,200

constant:

gridcol 0x808080

visible:

do

set color 255, 255, 255
draw image 1, 0,0
set color 128,128,128
draw rect 300,250,25,25,false

if mousebutton(0) and zone(1) and getrgb(mousex(),mousey()) <> gridcol then
current = getrgb(mousex(),mousey())
set colori current
draw rect 301, 251, 23, 23, true
endif
redraw
wait 10

until keydown(27) or not running()

function getrgb(x, y)
return pixeli(x, y) AND 0xffffff
endfunc

Peter

  • Guest
Re: SpriteEditor
« Reply #13 on: November 17, 2014 »
Hi Johnno,

this is what you need.
Code: [Select]
set window 0,0,640,480
set color 0,0,0
set redraw off
cls

load image 1, "colourpatch.png"

visible:
r5;g5;b5

while keydown(27)=0
set color 0,0,0,255
cls
set color 255, 255, 255,255
draw image 1, 0,0
set color 128,128,128
draw rect 300,250,25,25,false
 
set color 255,255,255,255
set caret 10,400
wln str(mousex())
set caret 10,410
wln str(mousey())
set caret 10,420
wln str(current)

if mousebutton(0) and mousex() >=0 and mousex() <=288 and mousey() >=0 and mousey() <=201 then
  current = pixeli(mousex(),mousey())
r5 = getR(current)
   g5 = getG(current)
   b5 = getB(current)
rem set color r5,g5,b5
rem draw rect 301, 251, 23, 23, 1
endif

set color r5,g5,b5
draw rect 301, 251, 23, 23, 1

redraw
wait 10
wend

function getB(n_c)
    return n_c AND 255
endfunc   

function getG(n_c)
    return (n_c SHR 8) AND 255
endfunc   

function getR(n_c)
    return (n_c SHR 16) AND 255
endfunc

johnno56

  • Guest
Re: SpriteEditor
« Reply #14 on: November 17, 2014 »
I just figured out the same result and was about to let you know... I figured out the reason why I couldn't see it. No coffee! Well, that's my excuse, and I'm sticking with that one. Many thanks.

Now that problem is out of the way, I can concentrate on the next one...

J