The Magical Counter

I've been lurking around the forum for a while now, kinda intimated to share any work on this project as it is my first ever adventure into coding, and I was a bit worried I/it would fail completely - But somehow, after much hard work and long nights trying to wrap my head around this whole thing I finally feel I have something worth sharing:

Magical_Counter_2P_demo_01

I really like Magic the Gathering and I knew I needed a "simple" project to learn scripting/coding, but also something that could keep me motivated - so I thought, "Hey way not do a counter for when I am playing magic."
Immediately when I stated sketching I felt the limitations of black and white was a blessing - the 1 bit limitation almost immediately took me to a dungeon setting.

The "game" has crank support if you really wanna crank that damage (which I suspect will feel pretty great) - currently there is only 2 player and only 3 avatars to select from, but I have some more stuff planned.

To do:

  • Add more avatars, I got a barbarian and a witch in mind - and thinking a bard, dragon and druid could be some good additions as well? Any magic players out there who has some suggestions/wishes?
  • I am also thinking of adding some subtle music, but I haven't quite been able to hit the right tone yet, so I am hope to get hit by some inspiration.
  • Something that will make it more clear which character is selected.
  • 4 player support, but this is only on a mock up stage atm.
    MockUp_File_4P_001

On top of that, I do have some problems I have run into that maybe someone can help me figure out.

  • Is there a good way to remove a sprite once it has finished its animation (ex the gradient I have for the transition into the "game" after you have selected the avatars) - I tried various version of wait I found in the SDK but I must be missing something because I could not get it to work.

  • My text alignment is really frustrating example below - I would expect the 9 to appear where the 0 was.
    Text_Alignment_Issue

Anyway I hope you like the idea, and I intend to keep updating as I add more stuff - and also when I get me own PD and can test it IRL (crossing my fingers it will ship soon).

  • Fred
13 Likes

I really love your art! I don't play MTG but I look forward to seeing where this goes

2 Likes

yoursprite:remove()

https://sdk.play.date/inside-playdate/#m-graphics.sprite.remove

yourfont:drawTextAligned()

https://sdk.play.date/inside-playdate/#m-graphics.font.drawTextAligned

1 Like

I love the art! Will be sure to use this on my next MTG Draft, once you release the thing :blush:

2 Likes

Hi Matt, thanks for dropping by and for the links.

I am realising that my questions probably where a bit unclear in their wording, the removing of the sprite is not the issue as such, more that I would like for the removal to happen once the animation had finished, the working code is it is now looks like this (but it doesn't remove it, just moves it out of frame - which I guess is not ideal?):

function PlayerSelector:transition()
    
        -- Animation lines -- IN
        local geo = playdate.geometry
        local y=-480
        local x=0
        local y2 = y+=400
        local downLine = geo.lineSegment.new(x, y, x, y2)
        local upLine = geo.lineSegment.new(x, y2, x, y)
        local bounceTimingIn = 2000
            
        -- Creating the animator 
        self.transitionAnimationIn = Animator.new(bounceTimingIn, upLine, playdate.easingFunctions.linear)
        self.transitionAnimationIn.repeatCount = 0
        
        self.BgBlackFillSprite:setAnimator(self.transitionAnimationIn)
        self.playerTextSprite:remove()

end

I have been trying to figure out how to use something like "playdate.wait()", to set a timer and then remove the sprite afterwards, but I can't really get my head around how to to that. When I put it in like:

playdate.wait(2000)
self.BgBlackFillSprite:remove()

I just get an error:
"playerSelector/playerSelector.lua:279: playdate.wait() may not be called from an event handler"
I know this might be a bit basic, but I am kinda lost as to what this means.


As for the text alignment, I have also used the reference you send, but I must be doing something wrong because the code looks like this but still seem to have alignment "left".

function self.p_hPBox:draw() -- behøver det være en funktion?

        local x = 118
        local y = 95
    
            gfx.setColor(gfx.kDrawModeBlackTransparent)
            gfx.fillRect(0,0,400,240)
            gfx.setImageDrawMode(gfx.kDrawModeNXOR)
    
            gfx.pushContext()
            gfx.setFontFamily(bigNumbersFont)
            gfx.drawTextInRect(self.text,x,y,199,240,kTextAlignment.right)
            gfx.popContext()
    
    end

Hope this clears it up a bit.

@donkee thank you! That is really awesome to hear :smiley:

@laplab Thanks! that is super encouraging to hear :smiley: I can't wait to have a working version I can share.

1 Like

Check out the Timers section in the docs.
You probably want something like

playdate.timer.performAfterDelay(2000, function()
    self.BgBlackFillSprite:remove()
end)

Thanks again, that makes sense.
I understand what is supposed to happen (I think?) - But I must be missing something fundamental about the playdate.timer.performAfterDelay works because I have for the past 2 hours been googling and trying all possible variations of it.

Since the function I want to run to start the delay timer is self:transition(), and that should then do self.BgBlackFillSprite:remove() after 2000 ms- the below line makes sense to me, but it won't compile.

playdate.timer.performAfterDelay(2000, self:transition() self.BgBlackFillSprite:remove() end)

playerSelector.lua:222: ')' expected near 'self'
the above line being 222

I checked here: A list of helpful libraries and code - #96 by frankbsad as well which does something very similar, and to me I cannot see the error in my line of code.

The documentation also doesn't help much in this case for a complete newcomer to the world of coding Inside Playdate

I tried to break it down and eliminate possible errors in references or whatnot in my script:

function sampleFunction()
    print('hello')
end

playdate.timer.performAfterDelay(2000, sampleFunction() print('did it work?') end)

But, here I get the error: "')' expected near 'print'"

(I have had many instances in the process of making this little counter where I wanted a delay but have put it off, or found some workaround because I just seem to keep hitting a wall hehe)

You need to declare the function at the beginning of the callback:

playdate.timer.performAfterDelay(2000, function() -- this is what you are missing, I think
    self:transition() 
    self.BgBlackFillSprite:remove() 
end)
1 Like

You are an absolute legend!

The solution that works in my case

function PlayerSelector:transition()
    
    -- Animation lines -- IN
    local geo = playdate.geometry
    local y=-480 
    local x=0
    local y2 = y+=480
    local downLine = geo.lineSegment.new(x, y, x, y2)
    local upLine = geo.lineSegment.new(x, y2, x, y)
    local bounceTimingIn = 1200
        
    -- Creating the animator 
    self.transitionAnimationIn = Animator.new(bounceTimingIn, upLine, playdate.easingFunctions.linear)
    self.transitionAnimationIn.repeatCount = 0
    
    self.BgBlackFillSprite:setAnimator(self.transitionAnimationIn)
    self.playerTextSprite:remove()

    playdate.timer.performAfterDelay(2000, function() 
        self.BgBlackFillSprite:remove() 
    end)

end

also I had to remember to put playdate.timer.updateTimers() in playdate.update()

Designed the barbarian:
4p_Mockup_v002

1 Like

You need a couple of nil parameters in the list to make sure the alignment parameter is in the correct place in the function call.

gfx.drawTextInRect(self.text,x,y,199,240,nil,nil,kTextAlignment.right)

1 Like

Awesome! It works. Thanks!

1 Like

Added some extra transitions, characters and a bit of an effect when a player takes damage. I have some details I want to add to the player selector screen so it does not feel as empty - but I think I might move on to implementing 3 and 4 player option.
Magical_Counter_2P_demo_02

2 Likes

Got a bit side tracked, but finally had some time to work on it again, 4 player is working now, so now I just need to add the choice of 2,3 or 4 player.
I decided that the layout worked better without the separators in 4 player.

Magical_Counter_4P_demo_01

Really cannot wait to try it on the device.

2 Likes

Hi! I love the idea :smiley:
I had a similar idea. A project that allows you to manage the reading of a book "you are the hero" (counting points, inventory, fights...). The small size of the Playdate is very useful for that!

Thanks a bunch!
Sounds like a fun idea :smiley: It really does seem like a handy device to keep around for that sort of things.

1 Like

All 3 player versions now work, both in standard and commander, still got some tweaks and things to add:
Magical_Counter_4P_demo_02

1 Like

IT HAS ARRIVED! Just got it today, it is beyond awesome to see this little program on on the device!


Also tweaked some stuff:
Magical_Counter_4P_demo_03

The playdate thought me how to code! (however basic it still is) Best money I ever spend :smiley:

4 Likes

Had the chance to take it for a test drive in a game of 3p commander, and everything worked as expected - Except the screen kept going to the lock screen, is there any way to tell the PD to not do that when the program is running?