I was really impressed with @Drew-Lo's implementation of Pong using Pulp.
It works really well and you'd never know there was a tile-based engine underneath it all.
Now that the SDK is out though, I figured I'd try my hand at Pong using the SDK.
I'm an experienced developer, but very new to game development. So I'm going to use this as a learning experience in learning the Playdate SDK, basic game development fundamentals, graphics, etc.
This thread will follow my progress in case it's helpful to others learning Playdate SDK development.
Start with the Examples
Distributed with the SDK, there's a ton of great examples.
It's totally worth checking them all out. Many of them have inspired me, given me ideas, and generally taught me some basic concepts for developing games.
And for this particular project, I used code from the AccelerometerTest as well as the Single File Example balls.lua
Both are similar, and gave me some basic structure for a ball bouncing around..
A bouncing ball
The first thing I got working was a bouncing ball, implemented as a sprite.
Since everything is a sprite, my playdate.update()
loop is just:
function playdate.update()
gfx.sprite.update()
end
The ball sprite has some basic logic on draw, to make it flash filled when it collides with something:
ballSprite.draw = function()
gfx.setColor(gfx.kColorBlack)
if ballSprite.collided then
gfx.fillCircleAtPoint(radius, radius, radius)
ballSprite.collided = false
else
gfx.drawCircleAtPoint(radius, radius, radius)
end
end
I then use a update
function on the sprite, to have the logic of how the ball moves.
I'm not going to bother with all the code here, but there's basically some bounds checking to see if we've hit a wall, in which case we adjust the speeds (dx, dy) to account for bouncing off. Then we eventually do
ballSprite.moveTo(newX, newY)
to move the ball along.
Later I think this is where I'll need to deal with collisions with the paddles, as well as "goal" conditions, instead of bouncing off the end walls.
DPad Paddle
Next I added a paddle for one player, that will use the directional-pad (dpad) to control it. This is just another sprite, with a simple fillRect
in the draw function.
The update
for this sprite looks at whether the directional buttons are pressed, and if so, moves:
dpadPlayerSprite.update = function()
if playdate.buttonIsPressed( playdate.kButtonUp ) then
if dpadPlayerSprite.y > 20 then
-- TODO could this be animated to be more smooth?
-- would I need a higher framerate?
dpadPlayerSprite:moveBy( 0, -DPAD_SPEED ) -- currently 10
end
elseif playdate.buttonIsPressed( playdate.kButtonDown ) then
if dpadPlayerSprite.y < 220 then
dpadPlayerSprite:moveBy( 0, DPAD_SPEED )
end
end
end
This feels pretty good to me, although I wonder if it could be more smooth... maybe the whole thing running at a higher framerate?
Crank Paddle
The other player will control their paddle with the crank.
I'm not really sure how well this will work as a control mechanism, but its fun to use the crank for stuff, and it seems cool to try to make a two-player, simultaneous-play, on one device.
crankPlayerSprite.update = function()
local change = playdate.getCrankChange()
local normalizedCrankInput = math.floor(change * CRANK_SCALE)
normalizedCrankInput = math.min(MAX_CRANK_SPEED, normalizedCrankInput)
normalizedCrankInput = math.max(-MAX_CRANK_SPEED, normalizedCrankInput)
if crankPlayerSprite.y < 20 then
normalizedCrankInput = math.max(0, normalizedCrankInput)
elseif crankPlayerSprite.y > 220 then
normalizedCrankInput = math.min(0, normalizedCrankInput)
end
crankPlayerSprite:moveBy( 0, normalizedCrankInput )
end
This update checks the amount the crank has changed, potentially scaling it by some scaling factor. I'm not sure if the degrees of rotation of the crank should map directly to pixels moved.... although so far in my testing that feels like it might work. But I think this will really need to be tuned once the hardware is in-hand.
We also normalize here to have a MAX_CRANK_SPEED. Originally I thought this should be the same as the increment moved by the directional pad β to keep it fair β i.e., both paddles would have the same maximum speed.
But in playing with it, it felt better with this max speed a bit higher.... again, something to tune when playing with the actual hardware.
Summary
So there you have it... that's where we're at after the first hour or so of writing this code
Next step will be figuring out how the sprite collision system works, and using that for bouncing the ball off the paddles.
Feedback
I have two reason for writing this up...
- Maybe it helps others who are also learning this stuff
- To get feedback! I'd love for those more knowledgable on this stuff to give me some pointers of how I might do things better, cleaner, more efficiently, more elegantly, etc.
Thanks all!
I'm really having fun playing with this.
Here's the code (and a OS X compiled PDX):
Pongdate-0.0.1.zip (23.5 KB)